Example #1
0
     $data = $data['response']['GeoObjectCollection']['featureMember'][0];
     if ($data['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision'] == 'other') {
         $try_new = TRUE;
     }
 } else {
     $try_new = TRUE;
 }
 if ($try_new && strpos($address, ',')) {
     // It might be that the first element of the address is a business name.
     // Lets drop the first element and see if we get anything better!
     list(, $address_new) = explode(',', $address, 2);
     //$request_new = $url.urlencode($address);
     $param = $api_params['request_params']['address'];
     $params[$param] = urlencode($address_new);
     $request_new = build_request_url($url, $params, $api_params['method']);
     $mapresponse = get_http_request($request_new, NULL, $ratelimit);
     $data_new = json_decode($mapresponse, TRUE);
     if ($data_new['response']['GeoObjectCollection']['metaDataProperty']['GeocoderResponseMetaData']['found'] > 0 && $data_new['response']['GeoObjectCollection']['featureMember'][0]['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision'] != 'other') {
         $request = $request_new;
         $data = $data_new['response']['GeoObjectCollection']['featureMember'][0];
     }
 }
 if (!$reverse) {
     // If using reverse queries, do not change lat/lon
     list($location['location_lon'], $location['location_lat']) = explode(' ', $data['GeoObject']['Point']['pos']);
 }
 $data = $data['GeoObject']['metaDataProperty']['GeocoderMetaData']['AddressDetails'];
 $location['location_country'] = strtolower($data['Country']['CountryNameCode']);
 $location['location_state'] = $data['Country']['AdministrativeArea']['AdministrativeAreaName'];
 if (isset($data['Country']['AdministrativeArea']['SubAdministrativeArea'])) {
     $location['location_county'] = $data['Country']['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName'];
Example #2
0
function get_geolocation($address, $hostname)
{
    global $config;
    switch (strtolower($config['geocoding']['api'])) {
        case 'osm':
        case 'openstreetmap':
            $location['location_geoapi'] = 'openstreetmap';
            // Openstreetmap. The usage limits are stricter here. (http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy)
            $url = "http://nominatim.openstreetmap.org/search?format=json&addressdetails=1&limit=1&q=";
            $reverse_url = "http://nominatim.openstreetmap.org/reverse?format=json&";
            break;
        case 'google':
            $location['location_geoapi'] = 'google';
            // See documentation here: https:// developers.google.com/maps/documentation/geocoding/
            // Use of the Google Geocoding API is subject to a query limit of 2,500 geolocation requests per day.
            $url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=";
            $reverse_url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&";
            break;
        case 'mapquest':
        default:
            $location['location_geoapi'] = 'mapquest';
            // Mapquest open data. There are no usage limits.
            $url = "http://open.mapquestapi.com/nominatim/v1/search.php?format=json&addressdetails=1&limit=1&q=";
            $reverse_url = "http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&";
    }
    if ($address != "Unknown" && $config['geocoding']['enable']) {
        $reverse = FALSE;
        // Forward geocoding by default
        // If location string contains coordinates ([33.234, -56.22]) use Reverse Geocoding.
        $pattern = '/\\[\\s*([+-]*\\d+[\\d\\.]*)[,\\s]+([+-]*\\d+[\\d\\.]*)[\\s\\]]+/';
        if (preg_match($pattern, $address, $matches)) {
            $location['location_lat'] = $matches[1];
            $location['location_lon'] = $matches[2];
            $reverse = TRUE;
        }
        // If DNS LOC support is enabled and DNS LOC record is set, use Reverse Geocoding.
        if ($config['geocoding']['dns']) {
            // Ack! dns_get_record not only cannot retrieve LOC records, but it also actively filters them when using
            // DNS_ANY as query type (which, admittedly would not be all that reliable as per the manual).
            // Example LOC:
            //   "20 31 55.893 N 4 57 38.269 E 45.00m 10m 100m 10m"
            //
            // From Wikipedia: d1 [m1 [s1]] {"N"|"S"}  d2 [m2 [s2]] {"E"|"W"}
            //
            // Parsing this is something for Net_DNS2 as it has the code for it.
            include_once 'Net/DNS2.php';
            include_once 'Net/DNS2/RR/LOC.php';
            $resolver = new Net_DNS2_Resolver();
            $response = $resolver->query($hostname, 'LOC', 'IN');
            if ($response) {
                foreach ($response->answer as $answer) {
                    if (is_numeric($answer->degree_latitude)) {
                        $ns_multiplier = $answer->ns_hem == 'N' ? 1 : -1;
                        $ew_multiplier = $answer->ew_hem == 'E' ? 1 : -1;
                        $location['location_lat'] = round($answer->degree_latitude + $answer->min_latitude / 60 + $answer->sec_latitude / 3600, 7) * $ns_multiplier;
                        $location['location_lon'] = round($answer->degree_longitude + $answer->min_longitude / 60 + $answer->sec_longitude / 3600, 7) * $ew_multiplier;
                        $reverse = TRUE;
                    }
                }
            }
        }
        if ($reverse) {
            if ($config['geocoding']['api'] == 'google') {
                // latlng=40.714224,-73.961452
                $request = $reverse_url . 'latlng=' . $location['location_lat'] . ',' . $location['location_lon'];
            } else {
                // lat=51.521435&lon=-0.162714
                $request = $reverse_url . 'lat=' . $location['location_lat'] . '&lon=' . $location['location_lon'];
            }
        } else {
            $request = $url . urlencode($address);
        }
        $mapresponse = get_http_request($request);
        $data = json_decode($mapresponse, true);
        if ($config['geocoding']['api'] == 'google') {
            if ($data['status'] == 'OVER_QUERY_LIMIT') {
                // Return empty array for overquery limit (for later recheck)
                return array();
            }
            // Use google data only with good status response
            if ($data['status'] == 'OK') {
                $data = $data['results'][0];
                if ($data['geometry']['location_type'] == 'APPROXIMATE') {
                    // It might be that the first element of the address is a business name.
                    // Lets drop the first element and see if we get anything better!
                    list(, $address) = explode(',', $address, 2);
                    $mapresponse = get_http_request($url . urlencode($address));
                    $data_new = json_decode($mapresponse, true);
                    if ($data_new['status'] == 'OK' && $data_new['results'][0]['geometry']['location_type'] != 'APPROXIMATE') {
                        $data = $data_new['results'][0];
                    }
                }
            }
        } elseif (!isset($location['location_lat'])) {
            $data = $data[0];
            if (!count($data)) {
                // We seem to have hit a snag geocoding. It might be that the first element of the address is a business name.
                // Lets drop the first element and see if we get anything better! This works more often than one might expect.
                list(, $address) = explode(',', $address, 2);
                $mapresponse = get_http_request($url . urlencode($address));
                $data = json_decode($mapresponse, true);
                // We only want the first entry in the returned data.
                $data = $data[0];
            }
        }
    }
    print_debug("GEO-API REQUEST: {$request}");
    // Put the values from the data array into the return array where they exist, else replace them with defaults or Unknown.
    if ($config['geocoding']['api'] == 'google') {
        $location['location_lat'] = $data['geometry']['location']['lat'];
        $location['location_lon'] = $data['geometry']['location']['lng'];
        foreach ($data['address_components'] as $entry) {
            switch ($entry['types'][0]) {
                case 'locality':
                    $location['location_city'] = $entry['long_name'];
                    break;
                case 'administrative_area_level_2':
                    $location['location_county'] = $entry['long_name'];
                    break;
                case 'administrative_area_level_1':
                    $location['location_state'] = $entry['long_name'];
                    break;
                case 'country':
                    $location['location_country'] = strtolower($entry['short_name']);
                    break;
            }
        }
    } else {
        $location['location_lat'] = $data['lat'];
        $location['location_lon'] = $data['lon'];
        $location['location_city'] = strlen($data['address']['town']) ? $data['address']['town'] : $data['address']['city'];
        // Would be nice to have an array of countries where we want state, and ones where we want County. For example, USA wants state, UK wants county.
        $location['location_county'] = $data['address']['county'];
        $location['location_state'] = $data['address']['state'];
        $location['location_country'] = $data['address']['country_code'];
    }
    // Use defaults if empty values
    if (!strlen($location['location_lat'])) {
        $location['location_lat'] = $config['geocoding']['default']['lat'];
    }
    if (!strlen($location['location_lon'])) {
        $location['location_lon'] = $config['geocoding']['default']['lon'];
    }
    if (!strlen($location['location_city'])) {
        $location['location_city'] = 'Unknown';
    }
    if (!strlen($location['location_county'])) {
        $location['location_county'] = 'Unknown';
    }
    if (!strlen($location['location_state'])) {
        $location['location_state'] = 'Unknown';
    }
    if (!strlen($location['location_country'])) {
        $location['location_country'] = 'Unknown';
    }
    return $location;
}
Example #3
0
 *
 */
// FIXME: This is fairly messy and crude. Feel free to improve it!
$color = $message_tags['ALERT_STATE'] == "RECOVER" ? "good" : "danger";
// JSON data
$data = array("username" => $endpoint['username'], "channel" => $endpoint['channel']);
$data['attachments'][] = array('fallback' => $message_tags['TITLE'], 'title' => $message_tags['TITLE'], 'title_link' => $message_tags['ALERT_URL'], 'fields' => array(array('title' => 'Device/Location', 'value' => $message_tags['DEVICE_HOSTNAME'] . " (" . $message_tags['DEVICE_OS'] . ")" . PHP_EOL . $message_tags['DEVICE_LOCATION'], 'short' => TRUE), array('title' => 'Entity', 'value' => $message_tags['ENTITY_TYPE'] . " / " . $message_tags['ENTITY_NAME'] . (isset($message_tags['ENTITY_DESCRIPTION']) ? '
' . $message_tags['ENTITY_DESCRIPTION'] : ''), 'short' => TRUE), array('title' => 'Alert Message/Duration', 'value' => $message_tags['ALERT_MESSAGE'] . PHP_EOL . $message_tags['DURATION'], 'short' => TRUE), array('title' => 'Metrics', 'value' => str_replace("             ", "", $message_tags['METRICS']), 'short' => TRUE)), 'color' => $color);
/*
foreach ($graphs as $graph)
{
    $data['attachments'][] = array('fallback' => "Graph Image",
      'title' => $graph['label'],
      'image_url' => $graph['url'],
      'color' => 'danger');

}
*/
$data_string = json_encode($data);
// JSON + HTTP headers
$context_data = array('method' => 'POST', 'header' => "Connection: close\r\n" . "Content-Length: " . strlen($data_string) . "\r\n", 'content' => $data_string);
// Send out API call
$result = get_http_request($endpoint['url'], $context_data);
// Check if call succeeded
if ($result == "ok") {
    $notify_status['success'] = TRUE;
} else {
    $notify_status['success'] = FALSE;
}
unset($data, $result, $context_data);
// EOF
Example #4
0
function get_geolocation($address, $geo_db = array(), $dns_only = FALSE)
{
    global $config;
    $ok = FALSE;
    $location = array('location' => $address);
    // Init location array
    $location['location_geoapi'] = strtolower(trim($config['geocoding']['api']));
    if (!isset($config['geo_api'][$location['location_geoapi']])) {
        // Use default if unknown api
        $location['location_geoapi'] = 'openstreetmap';
    }
    $api_params =& $config['geo_api'][$location['location_geoapi']];
    // Link to api specific params
    $params = $api_params['params'];
    // Init base request params
    // GEO API KEY and rate limits
    $ratelimit = FALSE;
    if (strlen($config['geocoding']['api_key']) && isset($api_params['request_params']['key'])) {
        $param = $api_params['request_params']['key'];
        $params[$param] = escape_html($config['geocoding']['api_key']);
        // KEYs is never used special characters
        if (isset($api_params['ratelimit_key'])) {
            $ratelimit = $api_params['ratelimit_key'];
        }
    } else {
        if (isset($api_params['ratelimit'])) {
            $ratelimit = $api_params['ratelimit'];
        }
    }
    if (isset($api_params['request_params']['id'])) {
        $params[$api_params['request_params']['id']] = OBSERVIUM_PRODUCT . '-' . substr(get_unique_id(), 0, 8);
    }
    if (isset($api_params['request_params']['uuid'])) {
        $params[$api_params['request_params']['uuid']] = get_unique_id();
    }
    if (isset($config['geocoding']['enable']) && $config['geocoding']['enable']) {
        $reverse = FALSE;
        // by default forward geocoding
        $debug_msg = "Geocoding ENABLED, try detect device coordinates:" . PHP_EOL;
        // If device coordinates set manually, use Reverse Geocoding.
        if ($geo_db['location_manual']) {
            $location['location_lat'] = $geo_db['location_lat'];
            $location['location_lon'] = $geo_db['location_lon'];
            $reverse = TRUE;
            $debug_msg .= '  MANUAL coordinates - SET' . PHP_EOL;
        } else {
            if ($config['geocoding']['dns']) {
                /**
                 * Ack! dns_get_record not only cannot retrieve LOC records, but it also actively filters them when using
                 * DNS_ANY as query type (which, admittedly would not be all that reliable as per the manual).
                 *
                 * Example LOC:
                 *   "20 31 55.893 N 4 57 38.269 E 45.00m 10m 100m 10m"
                 *
                 * From Wikipedia: d1 [m1 [s1]] {"N"|"S"}  d2 [m2 [s2]] {"E"|"W"}
                 *
                 * Parsing this is something for Net_DNS2 as it has the code for it.
                 */
                if ($geo_db['hostname']) {
                    //include_once('Net/DNS2.php');
                    //include_once('Net/DNS2/RR/LOC.php');
                    $resolver = new Net_DNS2_Resolver();
                    try {
                        $response = $resolver->query($geo_db['hostname'], 'LOC', 'IN');
                    } catch (Net_DNS2_Exception $e) {
                        print_debug('  ' . $e->getMessage() . ' (' . $geo_db['hostname'] . ')');
                    }
                } else {
                    $response = FALSE;
                    print_debug("  DNS LOC enabled, but device hostname empty.");
                }
                if ($response) {
                    if (OBS_DEBUG > 1) {
                        var_dump($response->answer);
                    }
                    foreach ($response->answer as $answer) {
                        if (is_numeric($answer->latitude) && is_numeric($answer->longitude)) {
                            $location['location_lat'] = $answer->latitude;
                            $location['location_lon'] = $answer->longitude;
                            $reverse = TRUE;
                            break;
                        } else {
                            if (is_numeric($answer->degree_latitude) && is_numeric($answer->degree_longitude)) {
                                $ns_multiplier = $answer->ns_hem == 'N' ? 1 : -1;
                                $ew_multiplier = $answer->ew_hem == 'E' ? 1 : -1;
                                $location['location_lat'] = round($answer->degree_latitude + $answer->min_latitude / 60 + $answer->sec_latitude / 3600, 7) * $ns_multiplier;
                                $location['location_lon'] = round($answer->degree_longitude + $answer->min_longitude / 60 + $answer->sec_longitude / 3600, 7) * $ew_multiplier;
                                $reverse = TRUE;
                                break;
                            }
                        }
                    }
                    if (isset($location['location_lat'])) {
                        $debug_msg .= '  DNS LOC records - FOUND' . PHP_EOL;
                    } else {
                        $debug_msg .= '  DNS LOC records - NOT FOUND' . PHP_EOL;
                        if ($dns_only) {
                            // If we check only DNS LOC records but it not found, exit
                            print_debug($debug_msg);
                            return FALSE;
                        }
                    }
                }
            }
        }
        if ($reverse || !preg_match('/^<?(unknown|none)>?$/i', $address)) {
            /**
             * If location string contains coordinates use Reverse Geocoding.
             * Valid strings:
             *   Some location [33.234, -56.22]
             *   Some location (33.234 -56.22)
             *   Some location [33.234;-56.22]
             *   33.234,-56.22
             */
            $pattern = '/(?:^|[\\[(])\\s*(?<lat>[+-]?\\d+(?:\\.\\d+)*)\\s*[,; ]\\s*(?<lon>[+-]?\\d+(?:\\.\\d+)*)\\s*(?:[\\])]|$)/';
            if (!$reverse && preg_match($pattern, $address, $matches)) {
                if ($matches['lat'] >= -90 && $matches['lat'] <= 90 && $matches['lon'] >= -180 && $matches['lon'] <= 180) {
                    $location['location_lat'] = $matches['lat'];
                    $location['location_lon'] = $matches['lon'];
                    $reverse = TRUE;
                }
            }
            if ($reverse) {
                $debug_msg .= '  by REVERSE query (API: ' . strtoupper($config['geocoding']['api']) . ', LAT: ' . $location['location_lat'] . ', LON: ' . $location['location_lon'] . ') - ';
                $url = $api_params['reverse_url'];
                if (isset($api_params['reverse_params'])) {
                    // Additional params for reverse query
                    $params = array_merge($params, $api_params['reverse_params']);
                }
                if (!is_numeric($location['location_lat']) || !is_numeric($location['location_lat'])) {
                    // Do nothing for empty, skip requests for empty coordinates
                } else {
                    if (isset($api_params['request_params']['lat']) && isset($api_params['request_params']['lon'])) {
                        $ok = TRUE;
                        $param = $api_params['request_params']['lat'];
                        $params[$param] = $location['location_lat'];
                        $param = $api_params['request_params']['lon'];
                        $params[$param] = $location['location_lon'];
                    } else {
                        if (isset($api_params['request_params']['latlon'])) {
                            $ok = TRUE;
                            $param = $api_params['request_params']['latlon'];
                            $params[$param] = $location['location_lat'] . ',' . $location['location_lon'];
                        }
                    }
                }
            } else {
                $debug_msg .= '  by PARSING sysLocation (API: ' . strtoupper($config['geocoding']['api']) . ') - ';
                $url = $api_params['direct_url'];
                if (isset($api_params['direct_params'])) {
                    // Additional params for reverse query
                    $params = array_merge($params, $api_params['direct_params']);
                }
                if ($address != '') {
                    $ok = TRUE;
                    $param = $api_params['request_params']['address'];
                    $params[$param] = urlencode($address);
                    //$request = $url . urlencode($address);
                }
            }
            if (OBS_DEBUG > 1) {
                print_vars($api_params);
                print_vars($params);
            }
            if ($ok) {
                // Build request query
                $request = build_request_url($url, $params, $api_params['method']);
                // First request
                $mapresponse = get_http_request($request, NULL, $ratelimit);
                switch ($GLOBALS['response_headers']['code'][0]) {
                    case '4':
                        // 4xx (timeout, rate limit, forbidden)
                    // 4xx (timeout, rate limit, forbidden)
                    case '5':
                        // 5xx (server error)
                        $geo_status = strtoupper($GLOBALS['response_headers']['status']);
                        $debug_msg .= $geo_status . PHP_EOL;
                        if (OBS_DEBUG < 2) {
                            // Hide API KEY from output
                            $request = str_replace($api_params['request_params']['key'] . '=' . escape_html($config['geocoding']['api_key']), $api_params['request_params']['key'] . '=' . '***', $request);
                        }
                        $debug_msg .= '  GEO API REQUEST: ' . $request;
                        print_debug($debug_msg);
                        // Return old array with new status (for later recheck)
                        unset($geo_db['hostname'], $geo_db['location_updated']);
                        $location['location_status'] = $debug_msg;
                        $location['location_updated'] = format_unixtime($config['time']['now'], 'Y-m-d G:i:s');
                        //print_vars($location);
                        //print_vars($geo_db);
                        return array_merge($geo_db, $location);
                }
                $data = json_decode($mapresponse, TRUE);
                //print_vars($data);
                $geo_status = 'NOT FOUND';
                $api_specific = is_file($config['install_dir'] . '/includes/geolocation/' . $location['location_geoapi'] . '.inc.php');
                if ($api_specific) {
                    // API specific parser
                    require_once $config['install_dir'] . '/includes/geolocation/' . $location['location_geoapi'] . '.inc.php';
                    if ($data === FALSE) {
                        // Return old array with new status (for later recheck)
                        unset($geo_db['hostname'], $geo_db['location_updated']);
                        //$location['location_status']  = $debug_msg;
                        $location['location_updated'] = format_unixtime($config['time']['now'], 'Y-m-d G:i:s');
                        //print_vars($location);
                        //print_vars($geo_db);
                        return array_merge($geo_db, $location);
                    }
                } else {
                    if (!isset($location['location_lat'])) {
                        $data = $data[0];
                        if (!count($data) && strpos($address, ',')) {
                            // We seem to have hit a snag geocoding. It might be that the first element of the address is a business name.
                            // Lets drop the first element and see if we get anything better! This works more often than one might expect.
                            list(, $address_new) = explode(',', $address, 2);
                            //$request_new = $url.urlencode($address);
                            $param = $api_params['request_params']['address'];
                            $params[$param] = urlencode($address_new);
                            $request_new = build_request_url($url, $params, $api_params['method']);
                            $mapresponse = get_http_request($request_new, NULL, $ratelimit);
                            $data_new = json_decode($mapresponse, TRUE);
                            if (count($data_new[0])) {
                                // We only want the first entry in the returned data.
                                $data = $data_new[0];
                                $request = $request_new;
                            }
                        }
                    }
                }
                if (OBS_DEBUG > 1 && count($data)) {
                    var_dump($data);
                }
            } else {
                $geo_status = 'NOT REQUESTED';
            }
        }
    }
    if (!$api_specific) {
        // Nominatum
        if (!$reverse) {
            // If using reverse queries, do not change lat/lon
            $location['location_lat'] = $data['lat'];
            $location['location_lon'] = $data['lon'];
        }
        foreach (array('town', 'city', 'hamlet', 'village') as $param) {
            if (isset($data['address'][$param])) {
                $location['location_city'] = $data['address'][$param];
                break;
            }
        }
        $location['location_state'] = $data['address']['state'];
        $location['location_county'] = isset($data['address']['county']) ? $data['address']['county'] : $data['address']['state_district'];
        $location['location_country'] = $data['address']['country_code'];
    }
    // Use defaults if empty values
    if (!strlen($location['location_lat']) || !strlen($location['location_lon'])) {
        // Reset to empty coordinates
        $location['location_lat'] = array('NULL');
        $location['location_lon'] = array('NULL');
        //$location['location_lat'] = $config['geocoding']['default']['lat'];
        //$location['location_lon'] = $config['geocoding']['default']['lon'];
        //if (is_numeric($config['geocoding']['default']['lat']) && is_numeric($config['geocoding']['default']['lon']))
        //{
        //  $location['location_manual']     = 1; // Set manual key for ability reset from WUI
        //}
    } else {
        // Always round lat/lon same as DB precision (DECIMAL(10,7))
        $location['location_lat'] = round($location['location_lat'], 7);
        $location['location_lon'] = round($location['location_lon'], 7);
    }
    foreach (array('city', 'county', 'state') as $entry) {
        // Remove duplicate County/State words
        $param = 'location_' . $entry;
        $location[$param] = strlen($location[$param]) ? str_ireplace(' ' . $entry, '', $location[$param]) : 'Unknown';
    }
    if (strlen($location['location_country'])) {
        $location['location_country'] = strtolower($location['location_country']);
        $geo_status = 'FOUND';
    } else {
        $location['location_country'] = 'Unknown';
    }
    // Print some debug informations
    $debug_msg .= $geo_status . PHP_EOL;
    if (OBS_DEBUG < 2) {
        // Hide API KEY from output
        $request = str_replace($api_params['request_params']['key'] . '=' . escape_html($config['geocoding']['api_key']), $api_params['request_params']['key'] . '=' . '***', $request);
    }
    $debug_msg .= '  GEO API REQUEST: ' . $request;
    if ($geo_status == 'FOUND') {
        $debug_msg .= PHP_EOL . '  GEO LOCATION: ';
        $debug_msg .= country_from_code($location['location_country']) . ' (Country), ' . $location['location_state'] . ' (State), ';
        $debug_msg .= $location['location_county'] . ' (County), ' . $location['location_city'] . ' (City)';
        $debug_msg .= PHP_EOL . '  GEO COORDINATES: ';
        $debug_msg .= $location['location_lat'] . ' (Latitude), ' . $location['location_lon'] . ' (Longitude)';
    } else {
        $debug_msg .= PHP_EOL . '  QUERY DATE: ' . date('r');
        // This is requered for increase data in DB
    }
    print_debug($debug_msg);
    $location['location_status'] = $debug_msg;
    return $location;
}
Example #5
0
                 } else {
                     if ($matches[1] == 'Comment') {
                         continue;
                         // skip comments
                     }
                 }
             }
             $response .= $line . PHP_EOL;
         }
     }
 } else {
     // Use RIPE whois API query
     $whois_url = 'https://stat.ripe.net/data/whois/data.json?';
     $whois_url .= 'sourceapp=' . urlencode(OBSERVIUM_PRODUCT . '-' . get_unique_id());
     $whois_url .= '&resource=' . urlencode($ip);
     $request = get_http_request($whois_url);
     if ($request) {
         $request = json_decode($request, TRUE);
         // Convert to array
         if ($request['status'] == 'ok' && count($request['data']['records'])) {
             $whois_parts = array();
             foreach ($request['data']['records'] as $i => $parts) {
                 $key = $parts[0]['key'];
                 if (in_array($key, array('NetRange', 'inetnum', 'inet6num'))) {
                     $org = 0;
                     $whois_parts[0] = '';
                     foreach ($parts as $part) {
                         if (in_array($part['key'], array('Ref', 'source', 'nic-hdl-br'))) {
                             break;
                         } else {
                             if (in_array($part['key'], array('Organization', 'org', 'mnt-irt'))) {
Example #6
0
    $endpoint['url'] = 'https://redoxygen.net/sms.dll?Action=SendSMS';
}
// Default from value if not set
if ($endpoint['from'] == "") {
    $endpoint['from'] = 'Observium';
}
// Pre-pend from value to message
$message = $endpoint['from'] . " " . $message;
$url = $endpoint['url'];
// Remove common delimiters used in phone numbers, e.g. dot, dash, space, from recipient number
$recipient = str_replace('.', '', $endpoint['recipient']);
$recipient = str_replace('-', '', $recipient);
$recipient = str_replace(' ', '', $recipient);
// URL encode POST values
$recipient = urlencode($recipient);
$email = urlencode($endpoint['email']);
$password = urlencode($endpoint['password']);
$message = urlencode($message);
$acctid = urlencode($endpoint['acctid']);
// POST Data - ENSURE AccountId is the first parameter, their API seems to fail if not.
$postdata = "AccountId=" . $acctid . "&Email=" . $email . "&Password="******"&Recipient=" . $recipient . "&Message=" . $message;
$context_data = array('method' => 'POST', 'content' => $postdata);
// Send out API call and parse response into an associative array
$response = get_http_request($url, $context_data);
if ($response == '0000') {
    $notify_status['success'] = TRUE;
} else {
    $notify_status['success'] = FALSE;
}
unset($url, $send, $message, $response, $postdata, $context_data);
// EOF
Example #7
0
<?php

/**
 * Observium
 *
 *   This file is part of Observium.
 *
 * @package    observium
 * @subpackage alerting
 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2016 Observium Limited
 *
 */
$message = $message_tags['TITLE'] . PHP_EOL;
$message .= str_replace("             ", "", $message_tags['METRICS']);
// JSON data
$data_string = json_encode(array("originator" => $endpoint['originator'], "body" => $message));
// JSON data + HTTP headers
$context_data = array('method' => 'POST', 'header' => "Connection: close\r\n" . "Accept: application/json\r\n" . "Content-Type: application/json\r\n" . "Content-Length: " . strlen($data_string) . "\r\n" . "Authorization: AccessKey " . $endpoint['token'] . "\r\n", 'content' => $data_string);
// API URL to POST to
$url = $endpoint['url'];
// Send out API call and parse response into an associative array
$result = json_decode(get_http_request($url, $context_data), TRUE);
if ($result['message'] == 'SUCCESS') {
    $notify_status['success'] = TRUE;
} else {
    $notify_status['success'] = FALSE;
}
unset($message, $result, $context_data);
// EOF
foreach (dbFetchRows("SELECT COUNT(*) AS `count`, `os` FROM `devices` GROUP BY `os`") as $data) {
    $stats['devicetypes'][$data['os']] = $data['count'];
}
// Per-type counts
foreach (dbFetchRows("SELECT COUNT(*) AS `count`, `type` FROM `devices` GROUP BY `type`") as $data) {
    $stats['types'][$data['type']] = $data['count'];
}
// Per-apptype counts
foreach (dbFetchRows("SELECT COUNT(*) AS `count`, `app_type` FROM `applications` GROUP BY `app_type`") as $data) {
    $stats['app_types'][$data['app_type']] = $data['count'];
}
// Serialize and base64 encode stats array for transportation
$stat_serial = serialize($stats);
$stat_base64 = base64_encode($stat_serial);
$url = "http://update.observium.org/latest.php?i=" . $stats['ports'] . "&d=" . $stats['devices'] . "&v=" . OBSERVIUM_VERSION . "&stats=" . $stat_base64;
$data = rtrim(get_http_request($url));
if ($data) {
    list($omnipotence, $year, $month, $revision) = explode(".", $data);
    list($cur, $tag) = explode("-", OBSERVIUM_VERSION);
    /// FIXME. $tag is OBSERVIUM_TRAIN?
    list($cur_omnipotence, $cur_year, $cur_month, $cur_revision) = explode(".", $cur);
    $version_string = $omnipotence . '.' . $year . '.' . $month . '.' . $revision;
    file_put_contents($config['rrd_dir'] . '/version.txt', $version_string);
    if ($argv[1] == "--cron" || isset($options['q'])) {
        $fd = fopen($config['log_file'], 'a');
        fputs($fd, $string . "\n");
        fclose($fd);
    } else {
        if ($cur != $data) {
            echo "当前版本 : {$cur_revision}\n";
            if ($revision > $cur_revision || TRUE) {
function get_geolocation($address, $geo_db = array())
{
    global $config;
    $location = array('location' => $address);
    // Init location array
    switch (strtolower($config['geocoding']['api'])) {
        case 'osm':
        case 'openstreetmap':
            $location['location_geoapi'] = 'openstreetmap';
            // Openstreetmap. The usage limits are stricter here. (http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy)
            $url = "http://nominatim.openstreetmap.org/search?format=json&accept-language=en&addressdetails=1&limit=1&q=";
            $reverse_url = "http://nominatim.openstreetmap.org/reverse?format=json&accept-language=en&";
            break;
        case 'google':
            $location['location_geoapi'] = 'google';
            // See documentation here: https:// developers.google.com/maps/documentation/geocoding/
            // Use of the Google Geocoding API is subject to a query limit of 2,500 geolocation requests per day.
            $url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&language=en&address=";
            $reverse_url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&language=en&";
            break;
        case 'yandex':
            $location['location_geoapi'] = 'yandex';
            $url = "http://geocode-maps.yandex.ru/1.x/?format=json&lang=en_US&results=1&geocode=";
            $reverse_url = "http://geocode-maps.yandex.ru/1.x/?format=json&lang=en_US&results=1&sco=latlong&";
            break;
        case 'mapquest':
        default:
            $location['location_geoapi'] = 'mapquest';
            // Mapquest open data. There are no usage limits.
            $url = "http://open.mapquestapi.com/nominatim/v1/search.php?format=json&accept-language=en&addressdetails=1&limit=1&q=";
            $reverse_url = "http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&accept-language=en&";
    }
    if (isset($config['geocoding']['enable']) && $config['geocoding']['enable']) {
        $reverse = FALSE;
        // by default forward geocoding
        $debug_msg = "Geocoding启用, 尝试定位设备坐标." . PHP_EOL;
        // If device coordinates set manually, use Reverse Geocoding.
        if ($geo_db['location_manual']) {
            $location['location_lat'] = $geo_db['location_lat'];
            $location['location_lon'] = $geo_db['location_lon'];
            $reverse = TRUE;
            $debug_msg .= '  MANUAL coordinates - SET' . PHP_EOL;
        } else {
            if ($config['geocoding']['dns']) {
                /**
                 * Ack! dns_get_record not only cannot retrieve LOC records, but it also actively filters them when using
                 * DNS_ANY as query type (which, admittedly would not be all that reliable as per the manual).
                 *
                 * Example LOC:
                 *   "20 31 55.893 N 4 57 38.269 E 45.00m 10m 100m 10m"
                 *
                 * From Wikipedia: d1 [m1 [s1]] {"N"|"S"}  d2 [m2 [s2]] {"E"|"W"}
                 *
                 * Parsing this is something for Net_DNS2 as it has the code for it.
                 */
                if ($geo_db['hostname']) {
                    include_once 'Net/DNS2.php';
                    include_once 'Net/DNS2/RR/LOC.php';
                    $resolver = new Net_DNS2_Resolver();
                    try {
                        $response = $resolver->query($geo_db['hostname'], 'LOC', 'IN');
                    } catch (Net_DNS2_Exception $e) {
                        print_debug('  ' . $e->getMessage() . ' (' . $geo_db['hostname'] . ')');
                    }
                } else {
                    $response = FALSE;
                    print_debug("  DNS 位置已激活, 不过设备主机名为空.");
                }
                if ($response) {
                    if (OBS_DEBUG > 1) {
                        var_dump($response->answer);
                    }
                    foreach ($response->answer as $answer) {
                        if (is_numeric($answer->latitude) && is_numeric($answer->longitude)) {
                            $location['location_lat'] = $answer->latitude;
                            $location['location_lon'] = $answer->longitude;
                            $reverse = TRUE;
                            break;
                        } else {
                            if (is_numeric($answer->degree_latitude) && is_numeric($answer->degree_longitude)) {
                                $ns_multiplier = $answer->ns_hem == 'N' ? 1 : -1;
                                $ew_multiplier = $answer->ew_hem == 'E' ? 1 : -1;
                                $location['location_lat'] = round($answer->degree_latitude + $answer->min_latitude / 60 + $answer->sec_latitude / 3600, 7) * $ns_multiplier;
                                $location['location_lon'] = round($answer->degree_longitude + $answer->min_longitude / 60 + $answer->sec_longitude / 3600, 7) * $ew_multiplier;
                                $reverse = TRUE;
                                break;
                            }
                        }
                    }
                    if (isset($location['location_lat'])) {
                        $debug_msg .= '  通过DNS位置记录 - 找到' . PHP_EOL;
                    } else {
                        $debug_msg .= '  通过DNS位置记录 - 未找到' . PHP_EOL;
                    }
                }
            }
        }
        if ($reverse || !preg_match('/^<?(unknown|none)>?$/i', $address)) {
            /**
             * If location string contains coordinates use Reverse Geocoding.
             * Valid strings:
             *   Some location [33.234, -56.22]
             *   Some location (33.234 -56.22)
             *   Some location [33.234;-56.22]
             *   33.234,-56.22
             */
            $pattern = '/(?:^|[\\[(])\\s*(?<lat>[+-]?\\d+(?:\\.\\d+)*)\\s*[,; ]\\s*(?<lon>[+-]?\\d+(?:\\.\\d+)*)\\s*(?:[\\])]|$)/';
            if (!$reverse && preg_match($pattern, $address, $matches)) {
                if ($matches['lat'] >= -90 && $matches['lat'] <= 90 && $matches['lon'] >= -180 && $matches['lon'] <= 180) {
                    $location['location_lat'] = $matches['lat'];
                    $location['location_lon'] = $matches['lon'];
                    $reverse = TRUE;
                }
            }
            if ($reverse) {
                $debug_msg .= '  by REVERSE query (API: ' . strtoupper($config['geocoding']['api']) . ', LAT: ' . $location['location_lat'] . ', LON: ' . $location['location_lon'] . ') - ';
                if (!is_numeric($location['location_lat']) || !is_numeric($location['location_lat'])) {
                    // Do nothing for empty, skip requests for empty coordinates
                } else {
                    if ($config['geocoding']['api'] == 'google') {
                        // latlng=40.714224,-73.961452
                        $request = $reverse_url . 'latlng=' . $location['location_lat'] . ',' . $location['location_lon'];
                    } else {
                        if ($config['geocoding']['api'] == 'yandex') {
                            // geocode=40.714224,-73.961452
                            $request = $reverse_url . 'geocode=' . $location['location_lat'] . ',' . $location['location_lon'];
                        } else {
                            // lat=51.521435&lon=-0.162714
                            $request = $reverse_url . 'lat=' . $location['location_lat'] . '&lon=' . $location['location_lon'];
                        }
                    }
                }
            } else {
                $debug_msg .= '  by PARSING sysLocation (API: ' . strtoupper($config['geocoding']['api']) . ') - ';
                if ($address != '') {
                    $request = $url . urlencode($address);
                }
            }
            if ($request) {
                // First request
                $mapresponse = get_http_request($request);
                $data = json_decode($mapresponse, TRUE);
                $geo_status = 'NOT FOUND';
                if ($config['geocoding']['api'] == 'google') {
                    if ($data['status'] == 'OVER_QUERY_LIMIT') {
                        $debug_msg .= $geo_status;
                        print_debug($debug_msg);
                        // Return empty array for overquery limit (for later recheck)
                        return array('location_status' => $debug_msg);
                    }
                    // Use google data only with good status response
                    if ($data['status'] == 'OK') {
                        $data = $data['results'][0];
                        if ($data['geometry']['location_type'] == 'APPROXIMATE') {
                            // It might be that the first element of the address is a business name.
                            // Lets drop the first element and see if we get anything better!
                            list(, $address) = explode(',', $address, 2);
                            $request_new = $url . urlencode($address);
                            $mapresponse = get_http_request($request_new);
                            $data_new = json_decode($mapresponse, TRUE);
                            if ($data_new['status'] == 'OK' && $data_new['results'][0]['geometry']['location_type'] != 'APPROXIMATE') {
                                $request = $request_new;
                                $data = $data_new['results'][0];
                            }
                        }
                    }
                } else {
                    if ($config['geocoding']['api'] == 'yandex') {
                        $try_new = FALSE;
                        if ($data['response']['GeoObjectCollection']['metaDataProperty']['GeocoderResponseMetaData']['found'] > 0) {
                            $data = $data['response']['GeoObjectCollection']['featureMember'][0];
                            if ($data['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision'] == 'other') {
                                $try_new = TRUE;
                            }
                        } else {
                            $try_new = TRUE;
                        }
                        if ($try_new && strpos($address, ',')) {
                            // It might be that the first element of the address is a business name.
                            // Lets drop the first element and see if we get anything better!
                            list(, $address) = explode(',', $address, 2);
                            $request_new = $url . urlencode($address);
                            $mapresponse = get_http_request($request_new);
                            $data_new = json_decode($mapresponse, TRUE);
                            if ($data_new['response']['GeoObjectCollection']['metaDataProperty']['GeocoderResponseMetaData']['found'] > 0 && $data_new['response']['GeoObjectCollection']['featureMember'][0]['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision'] != 'other') {
                                $request = $request_new;
                                $data = $data_new['response']['GeoObjectCollection']['featureMember'][0];
                            }
                        }
                    } else {
                        if (!isset($location['location_lat'])) {
                            $data = $data[0];
                            if (!count($data) && strpos($address, ',')) {
                                // We seem to have hit a snag geocoding. It might be that the first element of the address is a business name.
                                // Lets drop the first element and see if we get anything better! This works more often than one might expect.
                                list(, $address) = explode(',', $address, 2);
                                $request_new = $url . urlencode($address);
                                $mapresponse = get_http_request($request_new);
                                $data_new = json_decode($mapresponse, TRUE);
                                if (count($data_new[0])) {
                                    // We only want the first entry in the returned data.
                                    $data = $data_new[0];
                                    $request = $request_new;
                                }
                            }
                        }
                    }
                }
                if (OBS_DEBUG > 1 && count($data)) {
                    var_dump($data);
                }
            } else {
                $geo_status = '没有要求';
            }
        }
    }
    // Put the values from the data array into the return array where they exist, else replace them with defaults or Unknown.
    if ($config['geocoding']['api'] == 'google') {
        $location['location_lat'] = $data['geometry']['location']['lat'];
        $location['location_lon'] = $data['geometry']['location']['lng'];
        foreach ($data['address_components'] as $entry) {
            switch ($entry['types'][0]) {
                case 'postal_town':
                case 'locality':
                    $location['location_city'] = $entry['long_name'];
                    break;
                case 'administrative_area_level_2':
                    $location['location_county'] = $entry['long_name'];
                    break;
                case 'administrative_area_level_1':
                    $location['location_state'] = $entry['long_name'];
                    break;
                case 'country':
                    $location['location_country'] = strtolower($entry['short_name']);
                    break;
            }
        }
    } else {
        if ($config['geocoding']['api'] == 'yandex') {
            list($location['location_lon'], $location['location_lat']) = explode(' ', $data['GeoObject']['Point']['pos']);
            $data = $data['GeoObject']['metaDataProperty']['GeocoderMetaData']['AddressDetails'];
            $location['location_country'] = strtolower($data['Country']['CountryNameCode']);
            $location['location_state'] = $data['Country']['AdministrativeArea']['AdministrativeAreaName'];
            $location['location_county'] = $data['Country']['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName'];
            $location['location_city'] = $data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['LocalityName'];
        } else {
            $location['location_lat'] = $data['lat'];
            $location['location_lon'] = $data['lon'];
            $location['location_city'] = strlen($data['address']['town']) ? $data['address']['town'] : $data['address']['city'];
            // Would be nice to have an array of countries where we want state, and ones where we want County. For example, USA wants state, UK wants county.
            $location['location_county'] = $data['address']['county'];
            $location['location_state'] = $data['address']['state'];
            $location['location_country'] = $data['address']['country_code'];
        }
    }
    // Use defaults if empty values
    if (!strlen($location['location_lat']) || !strlen($location['location_lon'])) {
        // Reset to empty coordinates
        $location['location_lat'] = array('NULL');
        $location['location_lon'] = array('NULL');
        //$location['location_lat'] = $config['geocoding']['default']['lat'];
        //$location['location_lon'] = $config['geocoding']['default']['lon'];
        //if (is_numeric($config['geocoding']['default']['lat']) && is_numeric($config['geocoding']['default']['lon']))
        //{
        //  $location['location_manual']     = 1; // Set manual key for ability reset from WUI
        //}
    } else {
        // Always round lat/lon same as DB precision (DECIMAL(10,7))
        $location['location_lat'] = round($location['location_lat'], 7);
        $location['location_lon'] = round($location['location_lon'], 7);
    }
    if (!strlen($location['location_city'])) {
        $location['location_city'] = '未知的城市';
    }
    if (!strlen($location['location_county'])) {
        $location['location_county'] = '未知的城镇';
    }
    if (!strlen($location['location_state'])) {
        $location['location_state'] = '未知的省份';
    }
    if (!strlen($location['location_country'])) {
        $location['location_country'] = '未知的国家';
    } else {
        $geo_status = 'FOUND';
    }
    // Print some debug informations
    $debug_msg .= $geo_status . PHP_EOL;
    $debug_msg .= '  GEO API REQUEST: ' . $request;
    if ($geo_status == 'FOUND') {
        $debug_msg .= PHP_EOL . '  GEOLOCATION: ';
        $debug_msg .= country_from_code($location['location_country']) . ' (Country), ' . $location['location_state'] . ' (State), ';
        $debug_msg .= $location['location_county'] . ' (County), ' . $location['location_city'] . ' (City)';
        $debug_msg .= PHP_EOL . '  GEO COORDINATES: ';
        $debug_msg .= $location['location_lat'] . ' (Latitude), ' . $location['location_lon'] . ' (Longitude)';
    } else {
        $debug_msg .= PHP_EOL . '  QUERY DATE: ' . date('r');
        // This is requered for increase data in DB
    }
    print_debug($debug_msg);
    $location['location_status'] = $debug_msg;
    return $location;
}
    case "status":
    case "mempool":
    case "processor":
        if (is_numeric($vars['entity_id']) && is_entity_permitted($vars['entity_id'], 'processor')) {
            $entity = get_entity_by_id_cache($vars['entity_type'], $vars['entity_id']);
            echo generate_entity_popup($entity, $vars['entity_type']);
        } else {
            print_warning("You are not permitted to view this entity.");
        }
        exit;
        break;
    case "mac":
        if (Net_MAC::check($vars['entity_id'])) {
            // Other way by using Pear::Net_MAC, see here: http://pear.php.net/manual/en/package.networking.net-mac.importvendors.php
            $url = 'http://api.macvendors.com/' . urlencode($vars['entity_id']);
            $response = get_http_request($url);
            if ($response) {
                echo 'MAC vendor: ' . $response;
            } else {
                echo '未找到';
            }
        } else {
            echo '不正确的MAC地址';
        }
        exit;
        break;
    default:
        print_error("未知的实体类型.");
        exit;
        break;
}
Example #11
0
    $stats['misc']['max_len']['port_label_num'] = dbFetchCell("SELECT MAX(LENGTH(`port_label_num`)) FROM `ports`");
    $stats['version'] = OBSERVIUM_VERSION;
    $stats['uuid'] = get_unique_id();
    return $stats;
}
$last_checked = get_obs_attrib('last_versioncheck');
if (!is_numeric($last_checked) || $last_checked < time() - 3600 || $options['u']) {
    $stats = get_instance_stats();
    // Serialize and base64 encode stats array for transportation
    $stat_serial = serialize($stats);
    $stat_base64 = base64_encode($stat_serial);
    $query = http_build_query(array('stats' => $stat_base64));
    $context_data = array('method' => 'POST', 'header' => "Connection: close\r\n" . "Content-Length: " . strlen($query) . "\r\n", 'content' => $query);
    //$context  = stream_context_create(array( 'http' => $context_data ));
    //$versions = file_get_contents( 'http://www.observium.org/versions.php', false, $context);
    $versions = get_http_request('http://www.observium.org/versions.php', $context_data);
    if ($versions = json_decode($versions, TRUE)) {
        if (OBSERVIUM_EDITION == "community") {
            $train = "ce";
        } elseif (OBSERVIUM_TRAIN == "stable") {
            $train = "stable";
        } else {
            $train = "current";
        }
        // this same as rolling
        $latest = $versions[$train];
        set_obs_attrib('latest_ver', $latest['version']);
        set_obs_attrib('latest_rev', $latest['revision']);
        set_obs_attrib('latest_rev_date', $latest['date']);
    }
    set_obs_attrib('last_versioncheck', time());
foreach (dbFetch("SELECT COUNT(*) AS count,os from devices group by `os`") as $data) {
    $stats['devicetypes'][$data['os']] = $data['count'];
}
// Per-type counts
foreach (dbFetch("SELECT COUNT(*) AS `count`, `type` FROM `devices` GROUP BY `type`") as $data) {
    $stats['types'][$data['type']] = $data['count'];
}
// Per-apptype counts
foreach (dbFetch("SELECT COUNT(*) AS `count`, `app_type` FROM `applications` GROUP BY `app_type`") as $data) {
    $stats['app_types'][$data['app_type']] = $data['count'];
}
// Serialize and base64 encode stats array for transportation
$stat_serial = serialize($stats);
$stat_base64 = base64_encode($stat_serial);
$url = "http://update.observium.org/latest.php?i=" . $stats['ports'] . "&d=" . $stats['devices'] . "&v=" . $config['version'] . "&stats=" . $stat_base64;
$data = get_http_request($url);
if ($data) {
    list($omnipotence, $year, $month, $revision) = explode(".", $data);
    list($cur, $tag) = explode("-", $config['version']);
    list($cur_omnipotence, $cur_year, $cur_month, $cur_revision) = explode(".", $cur);
    if ($argv[1] == "--cron" || isset($options['q'])) {
        $fd = fopen($config['log_file'], 'a');
        fputs($fd, $string . "\n");
        fclose($fd);
        shell_exec("echo {$omnipotence}.{$year}.{$month}.{$month} > " . $config['rrd_dir'] . "/version.txt ");
    } else {
        if ($cur != $data) {
            echo "Current Revision : {$cur_revision}\n";
            if ($revision > $cur_revision) {
                echo "最新版本   : {$revision}\n";
            }
Example #13
0
    }
    if ($user_info !== null) {
        $verified_user_id = $user_info['user_id'];
        $is_admin = $user_info['is_admin'];
        $login_id = $user_info['login_id'];
        $name = $user_info['name'];
        $avatar = $user_info['avatar'];
    }
    if ($is_logout) {
        $session_token = '';
    }
    setcookie('npclient', 'web', $expire);
    setcookie('nptoken', $session_token, $expire);
    return array('method' => $method, 'path' => $path, 'path_parts' => $url_parts, 'user_id' => $verified_user_id, 'login_id' => $login_id, 'logged_in' => $verified_user_id > 0, 'login_failure' => $login_failure, 'name' => $name, 'is_admin' => $is_admin, 'content_type' => $content_type, 'form' => $form, 'raw_content' => $raw_content, 'files' => $files, 'cookies' => $cookies, 'ip' => $ip, 'avatar' => $avatar, 'now' => time());
}
$request = get_http_request();
$file = process_url_mapping($request);
$log_not_found = $file == 'not_found.php';
// a little hacky.
if ($log_not_found) {
    $legacy_url = sql_query_item("SELECT * FROM `legacy_article_url` WHERE `old_url` = '" . sql_sanitize_string($request['path']) . "' LIMIT 1");
    if ($legacy_url != null) {
        $redir_url = trim($legacy_url['new_url']);
        header('HTTP/1.1 301 Moved Permanently');
        header('Location: ' . $redir_url);
        exit;
    }
}
// overwrites suppress_skin to true, possibly
require 'php/' . $file;
$response = execute($request);
function get_geolocation($address)
{
    global $config, $debug;
    switch (strtolower($config['geocoding']['api'])) {
        case 'osm':
        case 'openstreetmap':
            $location['location_geoapi'] = 'openstreetmap';
            /// Openstreetmap. The usage limits are stricter here. (http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy)
            $url = "http://nominatim.openstreetmap.org/search?format=json&addressdetails=1&limit=1&q=";
            $reverse_url = "http://nominatim.openstreetmap.org/reverse?format=json&";
            break;
        case 'google':
            $location['location_geoapi'] = 'google';
            // See documentation here: https://developers.google.com/maps/documentation/geocoding/
            /// Use of the Google Geocoding API is subject to a query limit of 2,500 geolocation requests per day.
            $url = "http://api.map.baidu.com/geocoder/v2/?address=";
            $reverse_url = "http://api.map.baidu.com/geocoder/v2/json?sensor=false&";
            break;
        case 'mapquest':
        default:
            $location['location_geoapi'] = 'mapquest';
            /// Mapquest open data. There are no usage limits.
            $url = "http://open.mapquestapi.com/nominatim/v1/search.php?format=json&addressdetails=1&limit=1&q=";
            $reverse_url = "http://open.mapquestapi.com/nominatim/v1/reverse.php?format=json&";
    }
    if ($address != "Unknown" && $config['geocoding']['enable']) {
        // If location string contains coordinates ([33.234, -56.22]) use Reverse Geocoding.
        $pattern = '/\\[\\s*([+-]*\\d+[\\d\\.]*)[,\\s]+([+-]*\\d+[\\d\\.]*)[\\s\\]]+/';
        if (preg_match($pattern, $address, $matches)) {
            $location['location_lat'] = $matches[1];
            $location['location_lon'] = $matches[2];
            if ($config['geocoding']['api'] == 'openstreetmap') {
                //latlng=40.714224,-73.961452
                $request = $reverse_url . 'latlng=' . $location['location_lat'] . ',' . $location['location_lon'];
            } else {
                //lat=51.521435&lon=-0.162714
                $request = $reverse_url . 'lat=' . $location['location_lat'] . '&lon=' . $location['location_lon'];
            }
        } else {
            $request = $url . urlencode($address);
        }
        $mapresponse = get_http_request($request);
        $data = json_decode($mapresponse, true);
        if ($config['geocoding']['api'] == 'openstreetmap') {
            if ($data['status'] == 'OVER_QUERY_LIMIT') {
                // Return empty array for overquery limit (for later recheck)
                return array();
            }
            // Use google data only with good status response
            if ($data['status'] == 'OK') {
                $data = $data['results'][0];
                if ($data['geometry']['location_type'] == 'APPROXIMATE') {
                    // It might be that the first element of the address is a business name.
                    // Lets drop the first element and see if we get anything better!
                    list(, $address) = explode(',', $address, 2);
                    $mapresponse = get_http_request($url . urlencode($address));
                    $data_new = json_decode($mapresponse, true);
                    if ($data_new['status'] == 'OK' && $data_new['results'][0]['geometry']['location_type'] != 'APPROXIMATE') {
                        $data = $data_new['results'][0];
                    }
                }
            }
        } elseif (!isset($location['location_lat'])) {
            $data = $data[0];
            if (!count($data)) {
                /// We seem to have hit a snag geocoding. It might be that the first element of the address is a business name.
                /// Lets drop the first element and see if we get anything better! This works more often than one might expect.
                list(, $address) = explode(',', $address, 2);
                $mapresponse = get_http_request($url . urlencode($address));
                $data = json_decode($mapresponse, true);
                /// We only want the first entry in the returned data.
                $data = $data[0];
            }
        }
    }
    if ($debug) {
        echo "GEO-API 需要: {$request}\n";
    }
    /// Put the values from the data array into the return array where they exist, else replace them with defaults or Unknown.
    if ($config['geocoding']['api'] == 'google') {
        $location['location_lat'] = $data['geometry']['location']['lat'];
        $location['location_lon'] = $data['geometry']['location']['lng'];
        foreach ($data['address_components'] as $entry) {
            switch ($entry['types'][0]) {
                case 'locality':
                    $location['location_city'] = $entry['long_name'];
                    break;
                case 'administrative_area_level_2':
                    $location['location_county'] = $entry['long_name'];
                    break;
                case 'administrative_area_level_1':
                    $location['location_state'] = $entry['long_name'];
                    break;
                case 'country':
                    $location['location_country'] = strtolower($entry['short_name']);
                    break;
            }
        }
    } else {
        $location['location_lat'] = $data['lat'];
        $location['location_lon'] = $data['lon'];
        $location['location_city'] = strlen($data['address']['town']) ? $data['address']['town'] : $data['address']['city'];
        /// Would be nice to have an array of countries where we want state, and ones where we want County. For example, USA wants state, UK wants county.
        $location['location_county'] = $data['address']['county'];
        $location['location_state'] = $data['address']['state'];
        $location['location_country'] = $data['address']['country_code'];
    }
    // Use defaults if empty values
    if (!strlen($location['location_lat'])) {
        $location['location_lat'] = $config['geocoding']['default']['lat'];
    }
    if (!strlen($location['location_lon'])) {
        $location['location_lon'] = $config['geocoding']['default']['lon'];
    }
    if (!strlen($location['location_city'])) {
        $location['location_city'] = 'Unknown';
    }
    if (!strlen($location['location_county'])) {
        $location['location_county'] = 'Unknown';
    }
    if (!strlen($location['location_state'])) {
        $location['location_state'] = 'Unknown';
    }
    if (!strlen($location['location_country'])) {
        $location['location_country'] = 'Unknown';
    }
    return $location;
}