Provide multiple mirrors if a file doesn't exist - php

I want a Mirror script which determines whether or not a certain file is accessible or not. If the mirror 1 is accessible, it will present the link to mirror 1. If mirror 1 is not accessible, it will present the link to mirror 2.
This so far is perfect, however I would like more mirrors. For example, if mirror 2 is unavailable, mirror 3 will be presented. If mirror 3 is unavailable, mirror 4 will
be presented and so on. I'm just not quite sure exactly how I could make this work. Has anyone got any suggestions? They would be highly appreciated. I've tried quite a lot of things already!
$mirror1 = "download1.exe";
$mirror2 = "download2.exe";
$header_response = get_headers($mirror1, 1);
if ( strpos( $header_response[0], "404" ) !== false )
{
echo '
Download Mirror 1
';
}
else
{
echo '
Download Mirror 2
';
}

Here's one way to do this:
$mirrors = array("download1.exe","download2.exe","download3.exe");
foreach($mirrors as $mirror) {
$header_response = get_headers($mirror, 1);
if (strpos( $header_response[0], "404" ) === false) {
echo 'Download from '.$mirror.'';
break; //removing break will show all available mirrors
}
}

You could put them all into an array. Then while() the response was === false, array_shift the next one out of the array and use it. Once it's not false, you'll echo the last one that was used.

Related

Why do I need curl-ca-bundle.crt?

For college, I've made a dynamic news website which uses openweathermap and ipinfo to create a little weather info line in the navbar. Initially it threw an error 'failed loading cafile stream' which was solved by installing a CA certificate in xampp/Apache/bin.
I've got a vague idea what this does - something in relation to making sure the peer's server certificate is valid, but I thought this was only necessary if you're using the 'curl' library? I'm not sure where in my code I've used this, unless it's related to where I pull info from one of the URLs? Just looking for clarification on where in the code 'curl' is used, what it's doing and why exactly I need this certificate. Also as an additional point, if I were to send my files to another person, would they also have to install this .crt file to xampp/apache/bin?
$query = #unserialize (file_get_contents('http://ip-api.com/php/'));
if ($query && $query['status'] == 'success') {
foreach ($query as $data) {
$data . "<br>";
}
}
$url="https://api.openweathermap.org/data/2.5/find?q=" . $query['city'] . "," . $query['countryCode'] . "&units=imperial&type=accurate&mode=xml&APPID=MYKEYCODE";
/*Converts an XML document to an object we can pull our info from*/
$getweather = simplexml_load_file($url);
$gettemp = $getweather->list->item->temperature['value'];
$celcius = ($gettemp - 32) * 5/9;
Thank you!
The slightly modified version I tried was as follows ( using json rather than XML for simplicity ):
$appkey='xxxxxxxxxx165be29428029b';
$data=(object)#unserialize( file_get_contents('http://ip-api.com/php/') );
if( $data ){
$city=$data->city;
$countryCode=$data->countryCode;
$url=sprintf('https://api.openweathermap.org/data/2.5/find?q=%s,%s&units=imperial&type=accurate&mode=json&APPID=%s',$city,$countryCode,$appkey);
$json=json_decode( file_get_contents( $url ) ) ?: false;
if( $json ){
$temp=$json->list[0]->main->temp;
$celcius=( ( $temp - 32 ) * 5/9 );
printf("<pre>City: %s\nCountry: %s\nTemperature: %sF (%sC)</pre>",$city,$countryCode,$temp,$celcius);
}
}
Which yielded:
City: Sheffield
Country: GB
Temperature: 42.17F (5.65C)
Which is a little odd as I have never been to Sheffield and it's nowhere near where I live but I know my ISP routes traffic all over the reekin so geo-location etc never works. That aside there were no errors and no requirement for a valid cacert
good luck

PHP gets all the keys of memcached always return false

I want to get the name of all keys for memcached, but Memcached::getAllKeys method always return false.
use contos 6.5 + memcached 1.4.31 + php-memcached-2.2.0 PECL
It looks like newer versions of memcached don't like nor support the getAllKeys method.
However it looks like someone made it work by setting
Memcached::OPT_BINARY_PROTOCOL = false
If it does not work I think you have to fall back to 1.4.23 version or install REDIS :P
I had the same problem on my live server. I was preparing a test to show the techs there how to replicate my problem:
$m = new Memcached();
$m->addServer(MEMCACHED_SERVER, MEMCACHED_PORT);
echo "added ". MEMCACHED_SERVER. ":". MEMCACHED_PORT. PHP_EOL;
$keys = [];
$stop = 100;
foreach( $m->getAllKeys() as $k){
array_push( $keys, $k );
if( --$stop == 0 ) break;
}
var_dump( $keys );
this would return 100 keys on my local R&D server, but an empty list on the live server. To show them there was definitely something in there I echoed a dump of a key in there that I knew for sure was there:
var_dump( $m->get( "cache:pool:70:230" ));
that line showed there was a key, but it also made getAllKeys to return a list of 100 entries more! I still believe this is a bug, but there is a workaround.
Edit: Turns out any redundant call before getallkeys fixes this: $m->getVersion(); would also make getAllKeys works

php RRD graph separation

I am trying to create RRD graphs with the help of PHP in order to keep track of the inoctets,outoctets and counter of a server.
So far the script is operating as expected but my problems comes when I am trying to produce 2 or more separate graphs. I am trying to produce (hourly, weekly , etc) graphs. I thought by creating a loop would solve my problem, since I have split the RRA in hours and days. Unfortunately I end up having 2 graphs that updating simultaneously as expected but plotting the same thing. Has any one encounter similar problem? I have applied the same program in perl with RRD::Simple,where is extremely easy and everything is adjusted almost automatically.
I have supplied under a working example of my code with the minimum possible data because the code is a bit long:
<?php
$file = "snmp-2";
$rrdFile = dirname(__FILE__) . "/snmp-2.rrd";
$in = "ifInOctets";
$out = "ifOutOctets";
$count = "sysUpTime";
$step = 5;
$rounds = 1;
$output = array("Hourly","Daily");
while (1) {
sleep (6);
$options = array(
"--start","now -15s", // Now -10 seconds (default)
"--step", "".$step."",
"DS:".$in.":GAUGE:10:U:U",
"DS:".$out.":GAUGE:10:U:U",
"DS:".$count.":ABSOLUTE:10:0:4294967295",
"RRA:MIN:0.5:12:60",
"RRA:MAX:0.5:12:60",
"RRA:LAST:0.5:12:60",
"RRA:AVERAGE:0.5:12:60",
"RRA:MIN:0.5:300:60",
"RRA:MAX:0.5:300:60",
"RRA:LAST:0.5:300:60",
"RRA:AVERAGE:0.5:300:60",
);
if ( !isset( $create ) ) {
$create = rrd_create(
"".$rrdFile."",
$options
);
if ( $create === FALSE ) {
echo "Creation error: ".rrd_error()."\n";
}
}
$t = time();
$ifInOctets = rand(0, 4294967295);
$ifOutOctets = rand(0, 4294967295);
$sysUpTime = rand(0, 4294967295);
$update = rrd_update(
"".$rrdFile."",
array(
"".$t.":".$ifInOctets.":".$ifOutOctets.":".$sysUpTime.""
)
);
if ($update === FALSE) {
echo "Update error: ".rrd_error()."\n";
}
$start = $t - ($step * $rounds);
foreach ($output as $test) {
$final = array(
"--start","".$start." -15s",
"--end", "".$t."",
"--step","".$step."",
"--title=".$file." RRD::Graph",
"--vertical-label=Byte(s)/sec",
"--right-axis-label=latency(min.)",
"--alt-y-grid", "--rigid",
"--width", "800", "--height", "500",
"--lower-limit=0",
"--alt-autoscale-max",
"--no-gridfit",
"--slope-mode",
"DEF:".$in."_def=".$file.".rrd:".$in.":AVERAGE",
"DEF:".$out."_def=".$file.".rrd:".$out.":AVERAGE",
"DEF:".$count."_def=".$file.".rrd:".$count.":AVERAGE",
"CDEF:inbytes=".$in."_def,8,/",
"CDEF:outbytes=".$out."_def,8,/",
"CDEF:counter=".$count."_def,8,/",
"COMMENT:\\n",
"LINE2:".$in."_def#FF0000:".$in."",
"COMMENT:\\n",
"LINE2:".$out."_def#0000FF:".$out."",
"COMMENT:\\n",
"LINE2:".$count."_def#FFFF00:".$count."",
);
$outputPngFile = rrd_graph(
"".$test.".png",
$final
);
if ($outputPngFile === FALSE) {
echo "<b>Graph error: </b>".rrd_error()."\n";
}
} /* End of foreach function */
$debug = rrd_lastupdate (
"".$rrdFile.""
);
if ($debug === FALSE) {
echo "<b>Graph result error: </b>".rrd_error()."\n";
}
var_dump ($debug);
$rounds++;
} /* End of while loop */
?>
A couple of issues.
Firstly, your definition of the RRD has a step of 5seconds and RRAs with steps of 12x5s=1min and 300x5s=25min. They also have a length of only 60 rows, so 1hr and 25hr respectively. You'll never get a weekly graph this way! You need to add more rows; also the step seems rather short, and you might need a smaller-step RRA for hourly graphs and a larger-step one for weekly graphs.
Secondly, it is not clear how you're calling the graph function. You seem to be specifying:
"--start","".$start." -15s",
"--end", "".$t."",
"--step","".$step."",
... which would force it to use the 5s interval (unavailable, so the 1min one would always get used) and for the graph to be only for the time window from the start to the last update, not a 'hourly' or 'daily' as you were asking.
Note that the RRA you have defined do not define the time window of the graph you are asking for. Also, just because you have more than one RRA defined, it doesnt mean you'll get more than one graph unless oyu call the graph function twice with different arguments.
If you want a daily graph, use
"--start","end - 1 hour",
"--end",$t,
Do not specify a step as the most appropriate available will be used anyway. For a daily graph, use
"--start","end - 1 day"
"--end",$t,
Similarly, no need to specify a step.
Hopefully this will make it a little clearer. Most of the RRD graph options have sensible defaults, and RRDTool is pretty good at picking the correct RRA to use based on the graph size, time window, and DEF statements.

If statement not working with AND

I'm trying to make sure that my twitter feed is served a certain way, cached or new. I'm using the code below to try to make sure if the cached file is old and additionally if at the same time I still have enough attempts left in my twitter rate limit. Problem is that the statement isn't seeming to work right, yet I can't figure out why. I've tried with both operators '&&' and 'AND', and neither work. Any idea?
$json = file_get_contents("http://api.twitter.com/1/account/rate_limit_status.json", true);
$decode = json_decode($json, true);
$twitter_rate_remaining = $decode['remaining_hits'];
if(((time()-filectime($file)) > 1800) && ($twitter_rate_remaining > 5)) { //do something }
Note: we do not know what $file is from your question - where does it come from? What OS and filesystem are you using?
However, I suspect you want to be using filemtime to check for updates to a cached file.
It has nothing to do with && or AND, but what the boolean values of your two conditions are - that's what boolean logic means. If either of the values are false, then the whole test will be false.
Do some debugging:
var_dump(time());
var_dump(filectime($file));
var_dump(time() - filectime($file));
var_dump(time()-filectime($file)) > 1800); // output boolean true or false
var_dump($twitter_rate_remaining);
var_dump($twitter_rate_remaining > 5); // output boolean true or false;
var_dump((time()-filectime($file)) > 1800) && ($twitter_rate_remaining > 5)); // output boolean true or false
That way, you can see which of the conditions are false.
Ok, I figured it out. I did not have this included in my function. I had it outside. Doh!
$json = file_get_contents("http://api.twitter.com/1/account/rate_limit_status.json", true);
$decode = json_decode($json, true);
$twitter_rate_remaining = $decode['remaining_hits'];
So I wasn't able to get the $twitter_rate_remaining value until I moved it into it.

How to strip subdomains to get valid root domain using PHP?

Ok, here's what I'm looking for: from a list of links, I'm stripping everything but the domains. The result is a mixed list of domains and domain-names which represent subdomains.
stackoverflow.com
security.stackexchange.com
whoknows.test.co.uk
you.get.it.by.now.dont.you.com
What I want to do is to trim all list entries down to their VALID (=only existing) root domains like this:
stackoverflow.com
security.stackexchange.com
test.co.uk
-fail-
Currently I explode each line into an array and work my list from back to front, using curl to check each potential root domain for it's existance... as soon as curl throws back a HTTP code >= 200 and < 400, I regard the root domain to be found. When the end of each potential domain lookup is done and no valid domain has been found at all, the domain is considered to be non-existant.
input: stackoverflow.com
test: stackoverflow.com - succeeds and is the root domain
result: stackoverflow.com - valid root domain
input: whoknows.test.co.uk
test: co.uk - fails
test: test.co.uk - succeeds (theoretically) and is the root domain
result: test.co.uk - valid root domain
input: you.get.it.by.now.dont.you.com
test: you.com - fails
test: dont.you.com - fails
test: now.dont.you.com - fails
test: by.now.dont.you.com - fails
test: it.by.now.dont.you.com - fails
test: get.it.by.now.dont.you.com - fails
test: you.get.it.by.now.dont.you.com - fails
result: you.get.it.by.now.dont.you.com - invalid domain
Is there any alternative way to do this? I would like to stop heating up my webserver's CPU with 2 to X (=near to unlimited) curl look-ups for every domain on my 100.000+ list. Also, all these lookups take a bunch of time. Maybe - so I hope - there is a quicker solution to do this.
The catch? It has to work with PHP.
There are a bunch of shortcuts to acheive what you need.
For example, you already know that .co.uk and .com are TLDs, so checking these you can obviously skip.
The problem is with all the other crazy TLDs.
I suggest you take a look at the source for ruby-domain-name
They have done a lot of work using RFCs and known data, to try and process it the right way.
So...
I've been fiddling around with this for a long time now, looking for the potential bottlenecks and after a few days of back and forth I discovered that it's actually CURL (that's waiting for the individual servers to respond with a HTTP code) that's making things slower than needed.
In the end, I opted in for a different "gethostbyname" function that takes IP6 into account to solve my problem(s).
function my_gethostbyname($host, $try_a = FALSE)
{
$dns = gethostbynamel6($host, $try_a);
if ($dns == FALSE)
{
return FALSE;
}
else
{
return $dns[0];
}
}
function gethostbynamel6($host, $try_a = FALSE)
{
$dns = array();
$dns6 = #dns_get_record($host, DNS_AAAA);
if($dns6!== FALSE)
{
$dns = array_merge($dns, $dns6);
}
if ($try_a == TRUE)
{
$dns4 = #dns_get_record($host, DNS_A);
if($dns4!== FALSE)
{
$dns = array_merge($dns, $dns4);
}
}
else
{
$dns = $dns6;
}
$ip6 = array();
$ip4 = array();
foreach ($dns as $record)
{
if ($record["type"] == "A")
{
$ip4[] = $record["ip"];
}
if ($record["type"] == "AAAA")
{
$ip6[] = $record["ipv6"];
}
}
if (count($ip6) < 1)
{
if ($try_a == TRUE)
{
if (count($ip4) < 1)
{
return FALSE;
}
else
{
return $ip4;
}
}
else
{
return FALSE;
}
}
else
{
return $ip6;
}
}
As soon as the first domain-part actually resolves to an IP, (a) the domain exists and (b) is the root domain.
This spares me major time and the trick of this is that you're only as slow as your DNS resolution and some microsecs. The curl option I used before took around 3 seconds per call (sometimes up to the full timeout range I had set to 20 secs), depending on the target server's response time - if any.
The path I now chose is easy to understand: I end up with a list of resolving domains and - when needed - I can check those using curl "on demand" or using one or more CRON jobs "on interval".
I know that it's kind of a workaround, but splitting the problem into two tasks (1 = pre-check for root domain, 2 = check if domain returns expected HTTP code) makes the whole thing faster than trying to do the complete job at once using curl.
What I've learned from this...
When checking domains, try to resolve them first so you can spare yourself the timeout burden that comes with curl.
Curl is great for many tasks, but it's not the smartest way to try to do everything with it.
When you think you can't solve a problem more than you've tried to do, split the problem in two or more parts and check again. Chances are big that you'll discover a whole new world of options to enhance what you've got.
I hope this spares someone the burden of fiddling around with an alike problem for weeks. ;)
class DomainUtils {
function __construct(){
//only these super domains
$this->superDomains = array(
'.com',
'.gov',
'.org',
'.co.uk',
'.info',
'.co',
'.net',
'.me',
'.tv',
'.mobi'
);
}
//get super domain
public function getMainDomain($domain = null){
$domainChunks = explode('.', str_ireplace($this->superDomains, '', $domain));
if(sizeof($domainChunks) == 0){
return false;
}
foreach($domainChunks as $key => $domainChunk){
if($key < sizeof($domainChunks) - 1){
$domain = str_ireplace($domainChunk . '.', '', $domain);
}
}
return $domain;
}
}

Categories