Help with PHP and shell_exec!!!

Hi, I've been working on a PHP script which is "supposed" to find an individuals weather based on their geolocation. This script uses "shell_exec".

I have checked my syntax and it is correct, but there is still something missing; for when I call on the script using:

<form action='/weather.php' method='get'><br>
<input type='submit' name='submit' value='Check'><br>
</form>

I get a blank page :frowning:

Here is my script:

<?php

function getWeather() {
$ip = $_SERVER['REMOTE_ADDR']; 
$geo = shell_exec("/usr/bin/curl -s api.hostip.info/get_html.php?ip=$ip | /usr/bin/sed -e '1d;3d' -e's|C.*:||' -e's/...\(.*\)/\1/' -e's|-|%2d|' -e's/ /%20/' -e\s/'/%27/'");
$getAddress = "http://www.google.com/ig/api?weather=$geo";
$xml_str = file_get_contents($getAddress,0);
$xml = new SimplexmlElement($xml_str);
$count = 0;
echo '<div id="weather">';

foreach($xml->weather as $item) {

        foreach($item->current_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
        echo $new->condition['data'];
            echo $new->temp_f['data'];
            echo $new->temp_c['data'];
            echo $new->humidity['data'];
            echo $new->wind_condition['data'];
            echo '</div>';
            }

        foreach($item->forecast_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
            echo $new->day_of_week['data'];
            echo $new->condition['data'];
            echo $new->low['data'];
            echo $new->high['data'];
            echo '</div>';
            }

    }

echo '</div>';
}

getWeather();

?>

I'm a bit of a noob when it comes to this, so any help would be greatly appreciated. Thanks.

Jared

A blank page when calling a PHP script often means a fatal PHP error.

What does your PHP error log file say?

---------- Post updated at 01:54 ---------- Previous update was at 01:43 ----------

Also.....

I would not use PHP shell exec to execute cURL. I would use the normal PHP cURL function.

[RESOLVED]
I ended up getting this script to work with
file_get_contents and preg_match instead of cURL and SED.

Thanks for your help :slight_smile:

Normally when people post here and then they solve their problem, they post back with the solution, so others can benefit.

This is the second post of yours I have seen where you simply post back, "Problem Solved, Thanks!"

This is not the way to thank people. The proper way to thank the community is to post back your working code, the solution, so others can benefit.

Please post your working code. Thanks.

Well I WAS going to post the polished script under a different title because the script no longer uses "shell_exec()" , but I have no problem posting the WIP for now, so here it is:

<?php

function getWeather($ip=false) {
    
   if (!empty($_SERVER['HTTP_CLIENT_IP']))
    {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    $url = "http://api.hostip.info/get_html.php?ip=$ip";
    $geo = file_get_contents($url);
    if( preg_match('/City: (.*)\nIP:/', $geo, $matches) ){
        $results = $matches[1];
    }else{
        $results = 'getLocation failure';

    }

$location = urlencode($results);
$getAddress = "http://www.google.com/ig/api?weather=$location";
$xml_str = file_get_contents($getAddress,0);
$xml = new SimplexmlElement($xml_str);
$count = 0;
echo '<div id="weather">';
foreach($xml->weather as $item) {

foreach($item->forecast_information as $new) {
            echo $new->city['data'];
            }

        foreach($item->current_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
        echo $new->condition['data'];
            echo $new->temp_f['data'];
            echo $new->temp_c['data'];
            echo $new->humidity['data'];
            echo $new->wind_condition['data'];
            echo '</div>';
            }

        foreach($item->forecast_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
            echo $new->day_of_week['data'];
            echo $new->condition['data'];
            echo $new->low['data'];
            echo $new->high['data'];
            echo '</div>';
            }

    }

echo '</div>';
}

getWeather();

?>

Now maybe you can help me "beautify" the final output?
I would like for this to look nice for people and right now it's messy :slight_smile:
See here:

http://thefeedcast.net/knooph.com/x/weather.php

Thanks again :slight_smile:

Well, first of all, you will get much faster performance if you use the PHP function cURL() and not get_file_contents().

Here are some sample benchmarks from stackoverflow, file_get_contents VS CURL, what has better performance?

That's a huge difference.

FWIW, I always use curl() and not get_file_contents().

Nice, curl() sounds good. So how would I implement curl()?
Do I just replace "get_file_contents" with "curl()"?

You can visit the PHP man page for curl() there are plenty of examples.

You can also see my recent blog post where I implement curl in an example bit of code to check for a file in a failover scenario:

[PHP] Web Failover Code Using cURL and Shared Memory | The UNIX and Linux Forums Blog

Thanks!

---------- Post updated at 04:25 PM ---------- Previous update was at 04:07 PM ----------

So I take it I somehow have to replace get_file_contents with something like this:

 // create curl resource
        $ch = curl_init();

        // set url
        curl_setopt($ch, CURLOPT_URL, "$ip");

        //return the transfer as a string
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        // $output contains the output string
        $output = curl_exec($ch);

        // close curl resource to free up system resources
        curl_close($ch); 

Forgive me for I am trying, LOL :slight_smile:

No, you need to send a URL to curl() as a argument, not an IP address.

From my example in the blog post:

define('HEARTBEAT', 'myCDNexample.com/heartbeat.html');
curl_setopt($ch, CURLOPT_URL, HEARTBEAT);

This works:

<?php

function getWeather() {
    
   if (!empty($_SERVER['HTTP_CLIENT_IP']))
    {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    $url = "http://api.hostip.info/get_html.php?ip=$ip";
    define('LOCALE', $url);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, LOCALE);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_FAILONERROR, TRUE);
    $geo = curl_exec($ch);
    curl_close($ch);
    if( preg_match('/City: (.*)\nIP:/', $geo, $matches) ){
        $results = $matches[1];
    }else{
        $results = 'getLocation failure';

    }

$location = urlencode($results);
$getAddress = "http://www.google.com/ig/api?weather=$location";
$xml_str = file_get_contents($getAddress,0);
$xml = new SimplexmlElement($xml_str);
$count = 0;
echo '<div id="weather">';
foreach($xml->weather as $item) {

foreach($item->forecast_information as $new) {
            echo $new->city['data'];
            }

        foreach($item->current_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
	    echo $new->condition['data'];
            echo $new->temp_f['data'];
            echo $new->temp_c['data'];
            echo $new->humidity['data'];
            echo $new->wind_condition['data'];
            echo '</div>';
            }

        foreach($item->forecast_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
            echo $new->day_of_week['data'];
            echo $new->condition['data'];
            echo $new->low['data'];
            echo $new->high['data'];
            echo '</div>';
            }

    }

echo '</div>';
}

getWeather();

?>

Have I missed anything?

Yes,

First of all, PHP define() is used for constants, not variables, so you can't use a variable to define a constant :smiley:

Second, you are still using get_file_content() in another part of the script to get the contents of a URL. Change that to another curl() call. Maybe you can create a small function?

Remember, define() is only for constants. In my script, my URL is a constant, yours is a variable so you should not use define(). My code is example code and my example uses a constant, but your code uses a variable. (Hint: pass $url to curl(), not LOCALE).

---------- Post updated at 20:50 ---------- Previous update was at 20:40 ----------

For example.....

define('HOSTIP_QUERY', 'http://api.hostip.info/get_html.php?ip=');

// blah blah

$url = HOSTIP_QUERY.$ip;
curl_setopt($ch, CURLOPT_URL, $url);

define() statements (for constants) should be at the top of the script, or in a config file you read when the script start :smiley:

This works:

<?php

    define('QUERY_0', 'http://api.hostip.info/get_html.php?ip=');
    define('QUERY_1', 'http://www.google.com/ig/api?weather=');

function getWeather() {
    
   if (!empty($_SERVER['HTTP_CLIENT_IP']))
    {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    $url0 = QUERY_0.$ip;
    $ch0 = curl_init();
    curl_setopt($ch0, CURLOPT_URL, $url0);
    curl_setopt($ch0, CURLOPT_HEADER, 0);
    curl_setopt($ch0, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch0, CURLOPT_FAILONERROR, TRUE);
    $geo = curl_exec($ch0);
    curl_close($ch0);
    if( preg_match('/City: (.*)\nIP:/', $geo, $matches) ){
        $results = $matches[1];
    }else{
        $results = 'getLocation failure';

    }

    $location = urlencode($results);
    $url1 = QUERY_1.$location;
    $ch1 = curl_init();
    curl_setopt($ch1, CURLOPT_URL, $url1);
    curl_setopt($ch1, CURLOPT_HEADER, 0);
    curl_setopt($ch1, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch1, CURLOPT_FAILONERROR, TRUE);
    $xml_str = curl_exec($ch1);
    curl_close($ch1);
$xml = new SimplexmlElement($xml_str);
echo '<div id="weather">';
foreach($xml->weather as $item) {

foreach($item->forecast_information as $new) {
            echo $new->city['data'];
            }

        foreach($item->current_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
        echo $new->condition['data'];
            echo $new->temp_f['data'];
            echo $new->temp_c['data'];
            echo $new->humidity['data'];
            echo $new->wind_condition['data'];
            echo '</div>';
            }

        foreach($item->forecast_conditions as $new) {

            echo '<div class="weatherIcon">';
            echo '<img src="http://www.google.com/' .$new->icon['data'] . '"/><br/>';
            echo $new->day_of_week['data'];
            echo $new->condition['data'];
            echo $new->low['data'];
            echo $new->high['data'];
            echo '</div>';
            }

    }

echo '</div>';
}

getWeather();

?>

So how would I format the layout of the output page? See here:

Link Removed.

I just want to organize it better and label the output text (ie. Humidity, Conditions,Wind, etc...

No idea.... I don't see any output from here.....

I just updated the URL to the demo. Try it now :slight_smile:

Hahahah.... enjoy styling.

Thread closed. (link removed)

Open another thread if you need scripting help.