Check URL is an image or not using PHP - php

I'm trying to check if url is image, so I did use getheader; the getheader is working on localhost but not working on hosting server. I also tried to use getimagesize also it's working on localhost but not working on web hosting server even my php.ini is set to
allow_url_fopen = On
allow_url_include = On
for get_header my code is
$url = "https://hgtvhome.sndimg.com/content/dam/images/hgtv/fullset/2016/2/16/2/Orig-Paul-Schultz_Toybox-Home-kitchen-1.jpg.rend.hgtvcom.616.411.suffix/1455654217545";
$url_headers=get_headers($url, 1);
if(isset($url_headers['Content-Type'])){
$type=strtolower($url_headers['Content-Type']);
$valid_image_type=array();
$valid_image_type['image/png']='';
$valid_image_type['image/jpg']='';
$valid_image_type['image/jpeg']='';
$valid_image_type['image/jpe']='';
$valid_image_type['image/gif']='';
$valid_image_type['image/tif']='';
$valid_image_type['image/tiff']='';
$valid_image_type['image/svg']='';
$valid_image_type['image/ico']='';
$valid_image_type['image/icon']='';
$valid_image_type['image/x-icon']='';
if(isset($valid_image_type[$type])){
echo "Yes it's Images";
}
else
{
echo "no image";
}
}
var_dump of getheader on localhost display
array (size=11)
0 => string 'HTTP/1.0 200 OK' (length=15)
'Content-Type' => string 'image/jpeg' (length=10)
'Server' => string 'Apache' (length=6)
'X-Content-Type-Options' => string 'nosniff' (length=7)
'X-Frame-Options' => string 'SAMEORIGIN' (length=10)
'Content-Length' => string '38885' (length=5)
'Cache-Control' => string 'max-age=2522004' (length=15)
'Expires' => string 'Fri, 03 May 2019 08:55:29 GMT' (length=29)
'Date' => string 'Thu, 04 Apr 2019 04:22:05 GMT' (length=29)
'Connection' => string 'close' (length=5)
'Vary' => string 'User-Agent' (length=10)
But var_dump on web hosting server display
Array
(
[server] => AkamaiGHost, Apache
[content-length] => 0, 2077
[location] => https://www.foodnetwork.com/not-available.html
[cache-control] => max-age=0, max-age=433
[expires] => Thu, 04 Apr 2019 05:16:02 GMT, Thu, 04 Apr 2019 05:23:15 GMT
[date] => Thu, 04 Apr 2019 05:16:02 GMT, Thu, 04 Apr 2019 05:16:02 GMT
[connection] => keep-alive, keep-alive
[vary] => User-Agent, User-Agent, Accept-Encoding
[content-type] => text/html; charset=UTF-8
[access-control-allow-method] => GET
[server-timing] => edge; dur=0, cdn-cache; desc=HIT
[x-akamai-transformed] => 9 - 0 pmb=mRUM,3
[access-control-allow-origin] => *
[content-encoding] => gzip
)
and for getimagesize my code is
if (#getimagesize($url)) {
echo "image exists ";
} else {
echo "image does not exist ";
}
also is working on localhost but not working on web host server the var_dump of #getimagesize($url) is displaying :
bool(false)

As per you comment, You image url is wrong. Is should be : https://hgtvhome.sndimg.com/content/dam/images/hgtv/fullset/2016/2/16/2/Orig-Paul-Schultz_Toybox-Home-kitchen-1.jpg
You should remove image caching and image versioning at the time of checking.
Best solution to check weather file is image or not
Solution 1
if(#is_array(getimagesize($mediapath))){
$image = true;
} else {
$image = false;
}
Solution 2
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($_FILES['fupload']['tmp_name']);
$error = !in_array($detectedType, $allowedTypes);
Solution 3
$supported_image = array('gif','jpg','jpeg','png','bmp');
$src_file_name = 'https://hgtvhome.sndimg.com/content/dam/images/hgtv/fullset/2016/2/16/2/Orig-Paul-Schultz_Toybox-Home-kitchen-1.jpg';
$ext = strtolower(pathinfo($src_file_name, PATHINFO_EXTENSION));
if (in_array($ext, $supported_image)){
echo "it's image";
}
else {
echo 'not image';
}

You should follow redirect headers (codes 30x)
In this case the image seems 'not available' because the redirect is to a not available page, it seems. Maybe the URL is wrong?
What you should also watch out for: many content providers check at least for a HTTP referrer header or they deny access to images (to make crawling a bit harder). Others check for a previously set cookie. And finally some can use some complex token-based authentication (which I will not get into). But for the first issues and also following redirects, you should use Curl: https://www.php.net/manual/en/book.curl.php
Content-type headers are very often unreliable. I would recommend using the exif image type returned by getimagesize in result index 2, which you seem to be calling anyway.
So to recap: use Curl to set referrer and follow redirects and maybe propagate cookies from a previous referrer page that you might browse, and once you get the content use getimagesize to determine type.

#getimagesize function take much time to respond. use below code for quick respond
function image_urlexists($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ($code == 200); // verifica se recebe "status OK"
}
$url = 'https://www.example.com/static/cs/img/pages/home/security-card-xl.png';
if (image_urlexists($url))
echo "valid Url of image";
else
echo "Not valid url image";

Related

Vimeo API not responding to "If-Modified-Since" header

According to Vimeo API documentation:
The If-Modified-Since header enables you to return only those API resources that have been modified since a particular date and time.
The header looks like this:
If-Modified-Since: {ddd}, {D} {MMM} {YYYY} {HH}:{mm}:{ss} {Z}
NOTE: If your formatting codes are rusty, Tue, 20 Jun 2023 14:42:36 GMT is an example.
If none of the resources have been modified since this date, the API returns an empty response body and the HTTP status 304 Not Modified.
I'm using the Official PHP library for the Vimeo API.
According to GitHub issue #130, the PHP library's request() method accepts an array of headers. And this commit shows how the $headers array is passed and parsed:
public function request($url, $params = array(), $method = 'GET',
$json_body = true, array $headers = array())
// Set the headers
foreach ($headers as $key => $value) {
$curl_opts[CURLOPT_HTTPHEADER][] = sprintf('%s: %s', $key, $value);
}
But when I pass the future date shown in the example, I still receive a full list of videos rather than the "empty response body and the HTTP status 304 Not Modified" specified in the documentation.
What am I doing wrong?
$fields = array(
'created_time',
'modified_time'
);
$params = array(
'page' => $page,
'filter' => 'embeddable',
'filter_embeddable' => true,
'fields' => implode(',',$fields)
);
$headers = array(
'If-Modified-Since' => 'Tue, 20 Jun 2023 14:42:36 GMT'
);
$json_body = true;
$method = 'GET';
$response = $vimeo->request('/me/videos', $params, $method, $json_body, $headers);
Result:
Array
(
[0] => Array
(
[created_time] => 2018-06-05T19:27:18+00:00
[modified_time] => 2018-06-29T19:12:21+00:00
)
[1] => Array
(
[created_time] => 2016-06-02T03:01:40+00:00
[modified_time] => 2019-04-30T06:15:29+00:00
)
[2] => Array
(
[created_time] => 2016-05-29T05:31:46+00:00
[modified_time] => 2019-04-25T07:46:53+00:00
)
....
Edit
Based on this answer (not about Vimeo), it seems that the API might return the entire set of videos if even one of them was modified after the "If-Modified-Since" date.
If anything has changed in the entire response, then it will send the entire response to you.
But I'd still expect the result to be empty if the date is in the future. Am I misunderstanding?
Edit
Tom suggested that the Vimeo API ignores "If-Modified-Since" headers that are set in the future. I tried setting mine in the recent past, but I'm still getting results that were modified before that date:
$vimeo = new \Vimeo\Vimeo(false,false,$access_token);
$fields = array(
'modified_time'
);
$params = array(
'page' => 1,
'fields' => implode(',',$fields)
);
$method = 'GET';
$json_body = true;
$headers = array(
'If-Modified-Since' => 'Fri, 24 May 2019 14:42:36 GMT'
);
$response = $vimeo->request('/me/videos', $params, $method, $json_body, $headers);
echo"<pre>".print_r($response,true)."</pre>";
The result includes:
[21] => Array
(
[modified_time] => 2019-05-16T17:22:58+00:00
)
[22] => Array
(
[modified_time] => 2019-05-12T08:07:30+00:00
)
Edit
I was wrong. As mentioned above, I believe the entire response is returned if any item in the response has been modified since the "If-Modified-Since" timestamp. That made it look like the header wasn't working. But I set the timestamp as close as possible to the current time and I did get a "304 Not Modified" response, as Tom reported in his answer below. Others (content producers) also have access to the Vimeo account I'm testing against and I wasn't aware how recently they had modified content.
It's not documented by Vimeo, but I found out by experiment that:
When If-Modified-Since lies in the future, it is ignored.
Otherwise, the header works as expected. But take care of your timezones and possible clock-skew of a few seconds.
Vimeo's modification time is shown in the API response, in my case:
"modified_time": "2019-05-22T09:52:45+00:00",
If-Modified-Since: Wed, 22 May 2019 09:56:25 GMT returns a 304 Not Modified for my situation.
I've submitted a support request to Vimeo to clarify or change this behaviour.

Vimeo: how to use php official client to add a domain whitelist for a video?

I am using official Vimeo PHP client.
I can upload a video, and set privacy.embed to whitelist.
Then doc tells me:
To add a domain to the whitelist, send a PUT request to /videos/{video_id}/privacy/domains/{domain}.
I tried
$privacy_uri = $uri . "/privacy/domains/testdomain.tld";
$domain_add_response = $client->request($privacy_uri);
where
- $uri is the /vimeo/<video_id>
- $client is born from new Vimeo(CLIENT_ID, CLIENT_SECRET, VIMEO_TOKEN);
Problem
Printing the $domain_add_response I get a 405 error, probably because of Allow (see the following response dump)
Array
(
[body] =>
[status] => 405
[headers] => Array
(
[Server] => nginx
[Content-Type] => application/json
[Allow] => PUT,DELETE,OPTIONS
[X-Vimeo-DC] => ge
[Accept-Ranges] => bytes
[Via] => 1.1 varnish
[Content-Length] => 0
[Date] => Mon, 15 Apr 2019 08:30:47 GMT
[Connection] => keep-alive
[X-Served-By] => cache-bwi5125-BWI, cache-mxp19820-MXP
[X-Cache] => MISS, MISS
[X-Cache-Hits] => 0, 0
[X-Timer] => S1555317047.232635,VS0,VE148
[Vary] => Accept-Encoding
)
)
I imagine I must set the PUT method in my request, but ... how ?
Solution found looking at api source code: https://github.com/vimeo/vimeo.php/blob/master/src/Vimeo/Vimeo.php#L88
where the signature of request is
public function request($url, $params = array(), $method = 'GET', $json_body = true, array $headers = array()): array
I understand that I can fix the problem, simply passing an empty $params array and specifing PUT as request $method
I changed this line
$domain_add_response = $client->request($privacy_uri);
Into this form
$domain_add_response = $client->request($privacy_uri, [], 'PUT');
And it works as expected

Getting error "invalid_client" from Vimeo API on user authentication

I'm attempting to authenticate a user through Vimeo in order to view a list of their videos on the website.
I'm using the Vimeo php library https://github.com/vimeo/vimeo.php with no errors when including it in my code.
I get the authentication URL and am able to navigate to the Allow APP Access page on Vimeo and when I click "Allow" I'm getting the "invalid_client" error on my redirect page, even though they send back a code in the $_GET.
I'm thoroughly confused at this point since I've got the official API library and the APP is set up correctly as far as I can tell. I'm hoping someone might be able to point me in the right direction as to why I'm getting this error and how to fix it!
My Code:
//init Vimeo
require_once("modules/classes/Vimeo/autoload.php");
$lib = new \Vimeo\Vimeo($vimeo_id, $vimeo_secret, $vimeo_access);
if(!isset($_SESSION['vstate'])){
$_SESSION['vstate'] = base64_encode(openssl_random_pseudo_bytes(30));
}
$vimeo_authurl = $lib->buildAuthorizationEndpoint($redirecturi,'public private',$_SESSION['vstate']);
if(isset($_GET['code'])){
echo "Code returned: ".$_GET['code'];
if ($_SESSION['vstate'] != $_GET['state']) {
echo 'Something is wrong. Vimeo sent back a different state than this script was expecting. Please let an administrator know that this has happened.';
}
$tokens = $lib->accessToken($_GET['code'], $redirecturi);
if ($tokens['status'] == 200) {
echo 'Vimeo account successfully connected!';
$_SESSION['access_token'] = $tokens['body']['access_token'];
$lib->setToken($token['body']['access_token']);
} else {
echo 'Sorry, we were unable to connect to your Vimeo account due to the following error:<br/>{'.$tokens['body']['error']."} ".$tokens['body']['error_description'];
}
echo "<br/><br/><pre>";
print_r($tokens);
echo "</pre>";
exit();
}
The print_r($tokens) gives this:
Array
(
[body] => Array
(
[error] => invalid_client
[error_description] => A valid client ID must be provided along with any request made to Vimeo's API
)
[status] => 400
[headers] => Array
(
[Server] => nginx
[Content-Type] => application/json
[Expires] => Fri, 10 Mar 2017 03:11:17 GMT
[Cache-Control] => no-store
[Strict-Transport-Security] => max-age=15552000; includeSubDomains; preload
[Pragma] => no-cache
[X-UA-Compatible] => IE=edge
[X-XSS-Protection] => 1; mode=block
[X-Content-Type-Options] => nosniff
[X-Frame-Options] => sameorigin
[Content-Security-Policy-Report-Only] => default-src https: data: blob: 'unsafe-inline' 'unsafe-eval'; report-uri /_csp
[Accept-Ranges] => bytes
[Via] => 1.1 varnish
[Fastly-Debug-Digest] => 5da2a3ac863afd5f2ad0963779e0dbc4c54c7d97d19f87fd227c5eb8c92bd621
[Content-Length] => 126
[Date] => Fri, 10 Mar 2017 15:11:17 GMT
[Connection] => keep-alive
[X-Served-By] => cache-iad2146-IAD, cache-ord1731-ORD
[X-Cache] => MISS, MISS
[X-Cache-Hits] => 0, 0
[X-Timer] => S1489158677.346607,VS0,VE55
[Vary] => Accept,Vimeo-Client-Id,Accept-Encoding,User-Agent
)
)
So I'm not exactly sure why, but I created a new APP with the same details and this new APP seemed to authenticate fine.
The first APP I was having troubles with I had originally sent a request for Upload Access, but was denied (due to local testing links), so perhaps that was the underlying issue with the "invalid_client" error.

Facebook Ads API/SDK - The global ID [xxxx] is not allowed. Please use the application specific ID instead

I am trying to get the name associated with an Ad Account. Using the API calling /me gets my user info no problem. Calling /me/adaccounts gets me an object with a data node that is an array of account id objects which has an id node. I use this ID to try and get the Ad Account and I get the following error:
The global ID [xxxx] is not allowed. Please use the application specific ID instead.
The code is included below, can someone tell me what I am doing wrong?
FacebookSession::setDefaultApplication($config['id'], $config['secret']);
$session = new FacebookSession($accessToken);
$api = new Api($session);
echo '<pre>';
$adAccountsResponse = $api->call('/me/adaccounts','GET');
$adAccounts = $adAccountsResponse->getResponse();
foreach($adAccounts->data as $adAccount)
{
$adAccountId = $adAccount->account_id;
$adAccount = new AdAccount($adAccountId, null, $api);
$adAccount->read(array(AdAccountFields::NAME));
print_r($adAccount);
}
I did a print_r($api) and it says I am using version 2 of the API.
[responseHeaders:protected] => Array
(
[http_code] => HTTP/1.1 200 OK
[Last-Modified] => 2014-07-20T14:37:10+0000
[Facebook-API-Version] => v2.0
[ETag] => "XXXXXXXXXXXXXX"
[Content-Type] => application/json; charset=UTF-8
[Pragma] => no-cache
[Access-Control-Allow-Origin] => *
[X-FB-Rev] => 1454522
[Cache-Control] => private, no-cache, no-store, must-revalidate
[Expires] => Sat, 01 Jan 2000 00:00:00 GMT
[X-FB-Debug] => "XXXXXXXXXXXXXX"
[Date] => Wed, 15 Oct 2014 15:10:36 GMT
[Connection] => keep-alive
[Content-Length] => 234
)
Interesting enough when I use the Graph API Explorer switching between API version numbers using the token that I have I get the same user ID no matter what the version of the API. So something is messed up.
That is an extremely odd error to receive as it doesn't actually relate to adaccounts.
There is however an easier way to retrieve the list of attributes you want in a single call using connections of the object AdUser:
use FacebookAds\Object\AdUser;
use FacebookAds\Object\Fields\AdAccountFields;
$user = new AdUser('me');
$accounts = $user->getAdAccounts(array(AdAccountFields::NAME)));
foreach($accounts as $account) {
echo $account->name."\n";
}
You could try to add the Graph API version prefix to your call:
$adAccountsResponse = $api->call('/v2.1/me/adaccounts','GET');

PHP WebDAV server unable to perform PUT method using Windows

I'm trying to implement a PHP-based WebDAV server to be able to use it under OS Windows (more precisely Windows 7).
Everything works just fine, except for the PUT method. When I try to upload a file from the filesystem to the WebDAV server the request content-lenght is empty, meaning i can't read the file i want to put in the server.
Here is what I'm receiveng when I drag a file (simple .txt file) using Windows:
[HTTP_USER_AGENT] => Microsoft-WebDAV-MiniRedir/6.1.7601
[HTTP_TRANSLATE] => f
[CONTENT_LENGTH] => 0
[HTTP_VIA] => 1.1 squid.Sole:3128 (squid/2.7.STABLE9), 1.0 squidcache.Proxy6.CCSP:3129 (squid/2.6.STABLE24)
[PATH] => /bin:/usr/bin:/sbin:/usr/sbin
[SERVER_SOFTWARE] => Apache
[SERVER_PORT] => 80
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.0
[REQUEST_METHOD] => PUT
Uploading the same file using a dedicated webdav client, i get a valid response and the file is being uploaded. Here is what I get using CyberDuck client:
[HTTP_EXPECT] => 100-continue
[CONTENT_LENGTH] => 263
[CONTENT_TYPE] => text/plain
[HTTP_CONNECTION] => Keep-Alive
[HTTP_USER_AGENT] => Cyberduck/4.2.1 (9350) (Windows 7/6.1) (x86)
[HTTP_ACCEPT_ENCODING] => gzip,deflate
[PATH] => /bin:/usr/bin:/sbin:/usr/sbin
[SERVER_SOFTWARE] => Apache
[SERVER_PORT] => 80
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => PUT
The CONTENT-LENGTH field changed and the file is online on the server as i should be.
I will post my code fragment here:
$options = Array();
$options["path"] = $this->path;
$options["content_length"] = $_SERVER["CONTENT_LENGTH"];
$options["stream"] = fopen('php://input', 'r');
$stat = $this->PUT($options); // In the PUT method I fopen the destination file in "w"
if ($stat === false) {
$stat = "403 Forbidden";
} else if (is_resource($stat) && get_resource_type($stat) == "stream") {
$stream = $stat;
$stat = $options["new"] ? "201 Created" : "204 No Content";
if (!empty($options["ranges"])) {
if (0 == fseek($stream, $range[0]["start"], SEEK_SET)) {
$length = $range[0]["end"]-$range[0]["start"]+1;
if (!fwrite($stream, fread($options["stream"], $length))) {
$stat = "403 Forbidden";
}
} else {
$stat = "403 Forbidden";
}
}else {
while (!feof($options["stream"])) {
if (false === fwrite($stream, fread($options["stream"], 4096))) { //The fread reads nothing from the stream...
$stat = "403 Forbidden";
break;
}
}
}
fclose($stream);
}
What could I do to solve this issue? is there any thing to set in Windows to make it work or is it just my code who lacks something?
Windows will first create a 0-byte file. After this succeeds it will upload the entire file.

Categories