PHP Detecting if source image url link leads to a "broken" image? - php

Suppose you have a thumbnail generator script that accepts source images in the form of a URL. Is there a way to detect if the source URL is "broken" - whether nonexistent or leads to an non-image file?
Just brute force using getimagesize() or another PHP GD function is not a solution, since spoofed stray URL's that might not be images at all (http://example.com/malicious.exe or the same file, but renamed as http://example.com/malicious.jpg) could be input - such cases could easily be detected by PHP before having to invoke GD. I'm looking for GD pre-sanitizing before having GD try its battalion at parsing the file.
as a first step, the following regular expression checks if the URL is an image extension:
preg_match('#(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)([^\s]+(\.(?i)(jpg|png|gif|bmp))$)#', $txt,$url);

use file_exists function in php, you can check urls with it.
See documentation below, shows how to check img... exactly what you need
FILE EXISTS - http://www.php.net/manual/en/function.file-exists.php#93572
URL EXISTS - http://www.php.net/manual/en/function.file-exists.php#85246
Here is alternative code for checking the url. If you will test in browser replace \n with <br/>
<?php
$urls = array('http://www.google.com/images/logos/ps_logo2.png', 'http://www.google.com/images/logos/ps_logo2_not_exists.png');
foreach($urls as $url){
echo "$url - ";
echo url_exists($url) ? "Exists" : 'Not Exists';
echo "\n\n";
}
function url_exists($url) {
$hdrs = #get_headers($url);
echo #$hdrs[1]."\n";
return is_array($hdrs) ? preg_match('/^HTTP\\/\\d+\\.\\d+\\s+2\\d\\d\\s+.*$/',$hdrs[0]) : false;
}
?>
Output is as follows
http://www.google.com/images/logos/ps_logo2.png - Content-Type: image/png
Exists
http://www.google.com/images/logos/ps_logo2_not_exists.png - Content-Type: text/html; charset=UTF-8
Not Exists

I have used the following to detect attributes for remote images
$src='http://example.com/image.jpg';
list($width, $height, $type, $attr) = #getimagesize($src);
example (checking stackoverflows "Careers 2.0" image)
$src='http://sstatic.net/ads/img/careers2-ad-header-so.png';
list($width, $height, $type, $attr) = #getimagesize($src);
echo '<pre>';
echo $width.'<br>';
echo $height.'<br>';
echo $type.'<br>';
echo $attr.'<br>';
echo '</pre>';
If $height, $width etc is null the image is obvious not an image or the file does not exists. Using cURL is overkill and slower (even with CURLOPT_HEADER)

The only really reliable way is to request the image using file_get_contents(), and finding out its image type using getimagesize().
Only if getimagesize() returns a valid file type, can you rely that it is in fact a valid image.
This is quite resource heavy, though.
You could consider not doing any server-side checks at all, and adding an onerror JavaScript event to the finished image resource:
<img src="..." onerror="this.style.display = 'none'">

try for local files
<?php
if(file_exists($filename))
{
//do what you want
}
else
{
//give error that file does not exists
}
?>
for external domains
$headers = #get_headers($url);
if (preg_match("|200|", $headers[0])) {
// file exists
} else {
// file doesn't exist
}
Also you can use curl request for the same.

Fast Solution for broken or not found images link
i suggest you that don't use getimagesize() because it will 1st download image then it will check images size+if this will not image then it will throw exception so use below code
if(checkRemoteFile($imgurl))
{
//found url, its mean
echo "this is image";
}
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;
}
}
Note:
this current code help you to identify broken or not found url image this will not help you to identify image type or headers

You could check the HTTP status code (it should be 200) and the Content-type header (image/png etc.) of the HTTP response before you put the actual image through the generator.
If these two preconditions are ok, after retrieving the image you can call getimagesize() on it and see if it breaks, what MIME type it returns etc.

did you try file_get_contents() method?
http://php.net/manual/en/function.file-get-contents.php

onerror Event
Execute a JavaScript if an error occurs when loading an image:
The onerror event is triggered if an error occurs while loading an external file (e.g. a document or an image).
Example:
<!DOCTYPE html>
<html>
<body>
<img src="image.gif" onerror="myFunction()">
<p>A function is triggered if an error occurs when loading the image. The function shows an alert box with a text.
In this example we refer to an image that does not exist, therefore the onerror event occurs.</p>
<script>
function myFunction() {
alert('The image could not be loaded.');
}
</script>
</body>
</html>

Although not detecting broken links, might be useful for someone else...
onerror=""
<img src="PATH" onerror="this.src='NEW PATH'" />

Related

JpGraph php graph library - trouble embedding graph

I have managed to create a graph using JpGraph, I want to now take it a step further and embed this graph in my template/view php file.
So I put the graph code into a seperate php file to then embed however, when I try to embed it via
<embed src="templates/ctl008/graphshow.php" height=80em; width=160em;> </embed> it leaves me with a requested URL not found error. I have fiddled with the path and tried just: graphshow.php, ctl008/graphshow.php and other such variations. Is it my path that is not correct or is there something else I am missing? I have also tried to embed it with <img src="graphshow.php" /> . A funny quirk is when I turn on ini_set('display_errors', 1); error_reporting(E_ALL); and try to view the graph on its own I am left with an error message: JpGraph Error: HTTP headers have already been sent. Caused by output from file gd_image.inc.php at line 92. but if i turn off the error_reporting it displays the graph as expected. I would appreciate any pointers in the right direction with this :)
Here is my graphshow.php file:
<?php require_once ('../library/include/jpgraph/src/jpgraph.php');
require_once ('../library/include/jpgraph/src/jpgraph_line.php');
require_once ('../library/include/jpgraph/src/jpgraph_bar.php');
ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);
$gasArray = array();
foreach($searchArray as $gArray){
$gasArray[] = $gArray['GASVB'];
}
$stromArray = array();
foreach($searchArray as $sArray){
$stromArray[] = $sArray['STROVB'];
}
$olArray = array();
foreach($searchArray as $oArray){
$olArray[] = $oArray['OLVB'];
}
if(!empty($gasArray) || !empty($stromArray) || !empty($olArray)){
ob_end_clean();
$width= 1200;
$height = 400;
$graph = new Graph($width, $height);
$graph->SetScale('intint');
$graph->title->Set('Energie Verbrauch');
$graph->SetMargin(80,25,30,80);
$graph->xaxis->title->Set('Datum');
$graph->yaxis->title->Set('Verbrauch');
// print_r($dateArray);
$lineGas = new LinePlot($gasArray);
$lineGas->SetLegend('Gas');
$lineStrom = new LinePlot($stromArray);
$lineStrom->SetLegend('Strom');
$lineOl = new LinePlot($olArray);
$lineOl->SetLegend('ÖL');
$graph->Add($lineGas);
$graph->Add($lineStrom);
$graph->Add($lineOl);
$graph->Stroke();
}
?>
I'd like to start off with a few helpful links:
JpGraph Error: HTTP headers have already been sent
http://www.digialliance.com/docs/jpgraph/html/2210intro.html
https://coursesweb.net/php-mysql/jpgraph-graph-charts-plots-php
https://jpgraph.net/download/manuals/chunkhtml/ch05s05.html
now that that is out of the way, how I managed to get it working:
Starting with the advice/help in the above StackOverflow link I turned my seperate php file into a function the final line of my graphshow.php function was this: $graph->Stroke("charts/graphEnergy.png"); where charts is the folder I am saving in and graphEnergy.png is the name of the file being saved.
then in my view/template page I require_once('chart/ctl008/graphshow.php'); made my php file accessible, called my function like so generateGraph($gasArray, $stromArray, $olArray); and then in the html section embedded the graph with <img src="./charts/graphEnergy.png" /> What really tripped me up was needing to call the graph.png with the ./ before the charts/graphEnergy.php, and then I was able to display my bootiful graph on my view/template page. I hope this helps someone in the future :)
BoogaBooga

Convert API URL to “data:image/png;base64" by PHP

The following API URL has an output in PNG image:
http://qrfree.kaywa.com/?l=1&s=8&d=google.com
I want convert the API URL to “data:image/png;base64” (DATA URL / DATA URI) with the similar to the PHP code example below:
$image = ("<img src = http://qrfree.kaywa.com/?l=1&s=8&d=google.com"); // False! (only example!)
//or
$image = 'real-picture.png'; // True!
$imageData = base64_encode(file_get_contents($image));
$src = 'data:image/png;base64,'.$imageData;
echo '<img src="'.$src.'">';
However, the above code works with a real picture which has specified format and if replaced with the API URL, cannot read image path.
How the code should be corrected?
Assuming a web request to http://qrfree.kaywa.com/?l=1&s=8&d=google.com returns an image of type image/png, you can do ...
$image = "http://qrfree.kaywa.com/?l=1&s=8&d=google.com";
echo '<img src="data:image/png;base64,',
base64_encode(file_get_contents($image)),
'">';
file_get_contents() expects either a valid file name or a valid http(s) request. Your code was passing in something starting with some HTML <img ...

Pretty Photo load image via ajax frame

I have an angular app that will display some images. I am opening a prettyPhoto ajax window and passing the pathname to the URL. My script is loading the image fine, however, it isn't displaying the image how prettyPhoto traditionally displays a photo.
What do I need to do so it behaves like it is displaying a photo? i.e: has the fullscreen button, resizes the lightbox to the photo etc.
Is that even possible?
I am opening the lightbox via:
$scope.openLightbox = function()
{
if (typeof $.prettyPhoto.open !== "function")
{
$.fn.prettyPhoto({
social_tools:false,
deeplinking: false,
keyboard_shortcuts: false
});
$.prettyPhoto.open('resources/php/view/lightbox.php?ajax=true&path=' + $base64.encode($scope.currentFile));
return;
}
$.prettyPhoto.open('resources/php/view/lightbox.php?ajax=true&path=' + $base64.encode($scope.currentFile));
}
$scope.currentFile would be something like: data/39/my_image_name.jpg
and I am parsing the PHP like so:
$path = base64_decode($_GET['path']);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$mimeExt = explode('/', $mime);
if ($mimeExt[0] == 'image')
{
echo '<img width="100%" height="100%" src="data:image/' . $mimeExt[1] . ';base64,' . base64_encode(file_get_contents($path)) . '">';
}
elseif ($mimeExt[0] == 'video')
{
}
finfo_close($finfo);
Like I said above, the image is displaying just fine, I just want it to be displayed with the standard prettyPhoto image behavior. I understand this may not be possible.
EDIT
So turns out I didn't need AJAX afterall:
$scope.openLightbox = function()
{
if (typeof $.prettyPhoto.open !== "function")
{
$.fn.prettyPhoto({
social_tools:false,
deeplinking: false,
keyboard_shortcuts: false
});
$.prettyPhoto.open('resources/php/view/lightbox.php?path=' + $base64.encode($scope.currentFile));
return;
}
$.prettyPhoto.open('resources/php/view/lightbox.php?path=' + $base64.encode($scope.currentFile));
}
and finally my php which I am outputting the image directly to the browser so prettyPhoto thinks it is just loading an image
<?php
require("../config.php");
require("../connect.php");
session_start();
if (isset($_SESSION['ds_level']))
{
$path = base64_decode($_GET['path']);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$mimeExt = explode('/', $mime);
if ($mimeExt[0] == 'image')
{
header('Content-Type: image/' . $mimeExt[1]);
echo file_get_contents($path);
}
elseif ($mimeExt[0] == 'video')
{
//do other stuff to display video
}
finfo_close($finfo);
}
else
{
//-- no access
}
?>
What do I need to do so it behaves like it is displaying a photo? i.e: has the fullscreen button, resizes the lightbox to the photo etc.
Is that even possible?
Yes, it is possible. You need to create a dedicated directive, as specified in this Gist:
.directive('prettyp', function(){
return function(scope, element, attrs) {
$("[rel^='prettyPhoto']").prettyPhoto({deeplinking: false, social_tools: false});
}
})
To apply it, specify rel="prettyPhoto" in the anchor, like so:
<a prettyp ng-href="{{image.url}}" rel="prettyPhoto[main]" target="_blank" title="{{image.title}}">
HOW IT WORKS
The directive looks for a rel attribute starting with prettyPhoto, and applies the prettyPhoto magic to it.
EXAMPLE
I made a Plunk you can play around with: check the Plunk
IN YOUR CODE
To apply the directive in your code, you could replace:
echo '';
with:
echo '<img width="100%" height="100%" src="data:image/' . $mimeExt[1] . ';base64,' . base64_encode(file_get_contents($path)) . '">';
EDIT AFTER CHAT SESSION
As your images are protected with .htaccess, you have opted to work with a base64 version of your image, and why not?
However, it seems that if you wait until the user clicks the 'view' button in your app, it takes too long to go fetch the protected image and encode it, before passing it on to prettyPhoto:
I recommend you go fetch your image before the user clicks the view button, when the user selects the image in the list.
The long process of:
make an ajax call to php server;
have php app fetch image;
have php app encode image;
have angularjs/javaScript app store the base64 string
can then be done automatically, preventively, in the background.
The user experience would then be optimised.
So when the user does click the view button, the base64 version of the image can be passed to prettyPhoto straight away, without any server call: this would produce the same result as displayed in the plunkr I provided, when the button is pressed.

PHP Image not showing in HTML using img element

Hello there i have a php file with the included:
The image shows properly when i access the PHP file, however when I try to show it in the HTML template, it shows as the little img with a crack in it, so basically saying "image not found"
<img src="http://konvictgaming.com/status.php?channel=blindsniper47">
is what i'm using to display it in the HTML template, however it just doesn't seem to want to show, I've tried searching with next to no results for my specific issue, although I'm certain I've probably searched the wrong title
adding code from the OP below
$clientId = ''; // Register your application and get a client ID at http://www.twitch.tv/settings?section=applications
$online = 'online.png'; // Set online image here
$offline = 'offline.png'; // Set offline image here
$json_array = json_decode(file_get_contents('https://api.twitch.tv/kraken/streams/'.strtolower($channelName).'?client_id='.$clientId), true);
if ($json_array['stream'] != NULL) {
$channelTitle = $json_array['stream']['channel']['display_name'];
$streamTitle = $json_array['stream']['channel']['status'];
$currentGame = $json_array['stream']['channel']['game'];
echo "<img src='$online' />";
} else {
echo "<img src='$offline' />";
}
The url is not an image, it is a webpage with the following content
<img src='offline.png' alt='Offline' />
Webpages cannot be displayed as images. You will need to edit the page to only transmit the actual image, with the correct http-headers.
You can probably find some help on this by googling for "php dynamic image".
Specify in the HTTP header that it's a PNG (or whatever) image!
(By default they are interpreted as text/html)
in your status.php file, where you output the markup of <img src=... change it to read as follows
$image = file_get_contents("offline.png");
header("Content-Type: image/png");
echo $image;
Which will send an actual image for the request instead of sending markup. markup is not valid src for an img tag.
UPDATE your code modified below.
$clientId = ''; // Register your application and get a client ID at http://www.twitch.tv/settings?section=applications
$online = 'online.png'; // Set online image here
$offline = 'offline.png'; // Set offline image here
$json_array = json_decode(file_get_contents('https://api.twitch.tv/kraken/streams/'.strtolower($channelName).'?client_id='.$clientId), true);
header("Content-Type: image/png");
$image = null;
if ($json_array['stream'] != NULL) {
$channelTitle = $json_array['stream']['channel']['display_name'];
$streamTitle = $json_array['stream']['channel']['status'];
$currentGame = $json_array['stream']['channel']['game'];
$image = file_get_contents($online);
} else {
$image = file_get_contents($offline);
}
echo $image;
I suppose you change the picture dynmaclly on this page.
Easiest way with least changes will just be using an iframe:
<iframe src="http://konvictgaming.com/status.php?channel=blindsniper47"> </iframe>

PHP file_get_contents

I'm looking to create a PHP script where, a user will provide a link to a webpage, and it will get the contents of that webpage and based on it's contents, parse the contents.
For example, if a user provides a YouTube link:
http://www.youtube.com/watch?v=xxxxxxxxxxx
Then, it will grab the basic information about that video (thumbnail, embed code?)
Or they might provide a vimeo link:
http://www.vimeo.com/xxxxxx
Or even if they were to provide any link, without a video attached, such as:
http://www.google.com/
And it could grab just the page Title or some meta content.
I'm thinking I'd have to use file_get_contents, but I'm not exactly sure how to use it in this context.
I'm not looking for someone to write the entire code, but perhaps provide me with some tools so that I can accomplish this.
You can use either the curl or the http library. You send a http request, and can use the library to get the information from the http response.
I know this question is quite old, but I'll answer just in case someone hits it looking for the same thing.
Use oEmbed (http://oembed.com/) for YouTube, Vimeo, Wordpress, Slideshare, Hulu, Flickr and many other services. If not in the list or you want to make it more precise, you can use this:
http://simplehtmldom.sourceforge.net/
It's a sort of jQuery for PHP, meaning you can use HTML selectors to get portions of the code (i.e.: all the images, get the contents of a div, return only text (no HTML) contents of a node, etc).
You could do something like this (could be done more elegantly but this is just an example):
require_once("simple_html_dom.php");
function getContent ($item, $contentLength)
{
$raw;
$content = "";
$html;
$images = "";
if (isset ($item->content) && $item->content != "")
{
$raw = $item->content;
$html = str_get_html ($raw);
$content = str_replace("\n", "<BR /><BR />\n\n", trim($html->plaintext));
try
{
foreach($html->find('img') as $image) {
if ($image->width != "1")
{
// Don't include images smaller than 100px height
$include = false;
$height = $image->width;
if ($height != "" && $height >= 100)
{
$include = true;
}
/*else
{
list($width, $height, $type, $attr) = getimagesize($image->src);
if ($height != "" && $height >= 100)
$include = true;
}*/
if ($include == true)
{
$images = $images . '<div class="theImage"><img src="'.$image->src.'" alt="'.$image->alt.'" class="postImage" border="0" /></div>';
}
}
}
}
catch (Exception $e) {
// Do nothing
}
$images = '<div id="images">'.$images.'</div>';
}
else
{
$raw = $item->summary;
$content = str_get_html ($raw)->plaintext;
}
return (substr($content, 0 , $contentLength) . (strlen ($content) > $contentLength ? "..." : "") . $images);
}
file_get_contents() would work in this case assuming that you have allow_fopen_url set to true in your php.ini. What you would do is something like:
$pageContent = #file_get_contents($url);
if ($pageContent) {
preg_match_all('#<embed.*</embed>#', $pageContent, $matches);
$embedStrings = $matches[0];
}
That said, file_get_contents() won't give you much in the way of error handling other receiving the content on success or false on failure. If you would like to have more rich control over the request and access the HTTP response codes, use the curl functions and in particular, curl_get_info, to look at the response codes, mime types, encoding, etc. Once you get the content via either curl or file_get_contents() your code for parsing it to look for the HTML of interest will be the same.
Maybe Thumbshots or Snap already have some of the functionality you want?
I know that's not exactly what you are looking for, but at least for the embedded stuff that might be handy. Also txwikinger already answered your other question. But maybe that helps ypu anyway.

Categories