Issues (196)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

converters/GetLatLngFromGoogleUsingAddress.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Geocode an address-string to a set of coordinates using Google's free
5
 * geocoding services.
6
 *
7
 * see: http://code.google.com/apis/maps/documentation/geocoding/index.html
8
 *
9
 * CHECKS IF CURL / file_get_contents is available
10
 * Requirements: allow_url_fopen = on
11
 *
12
 * @author Ingo Schomme and Nicolaas Francken
13
 * @todo Implement CURL with fopen fallback
14
 * @todo Implement client-side selection when multiple results are found (through validation-errors and javasript)
15
 * @see http://code.google.com/apis/maps/documentation/services.html#Geocoding_Direct
16
 *
17
 * you can use
18
 * GetLatLngFromGoogleUsingAddress::get_placemark_as_array()
19
 */
20
21
class GetLatLngFromGoogleUsingAddress extends Object
22
{
23
24
    /**
25
     * For debugging.
26
     * needs to be static because we use static methods
27
     * in this class
28
     * @var Boolean for debugging
29
     */
30
    private static $debug = false;
31
32
    /**
33
     * location for API
34
     *
35
     * @var String
36
     */
37
    private static $geocode_url = "https://maps.googleapis.com/maps/api/geocode/json?address=%s";
38
39
    /**
40
     * Additional data to send to the Google Server
41
     *
42
     * @var array
43
     */
44
    private static $additional_params = [];
45
46
    /**
47
       * default user to first result that is returned.
48
       *
49
       * @var boolean
50
       */
51
    private static $default_to_first_result = true;
52
53
    /**
54
     *
55
     * tells you if CURL / file_get_contents is available
56
     * we recommend you set to true , unless it is not sure if CURL is available
57
     *
58
     * @var boolean
59
     */
60
    private static $server_side_available = true;
61
62
    /**
63
     * alternative to api key
64
     * @var string
65
     */
66
    private static $google_client_id = "";
67
68
    /**
69
     * alternative api key.
70
     *
71
     * This has been added so that you can set up IP restrictions and HTTP referrer
72
     * restrictions within the Google API Console (you can not have both at the same time).
73
     *
74
     * @var string
75
     */
76
    private static $alternative_google_map_api_key = "";
77
78
    /**
79
     * Get first placemark as flat array
80
     *
81
     * @param string $q
82
     * @param bool $tryAnyway
83
     * @param array $params
84
     *
85
     * @return array
86
     */
87
    public static function get_placemark_as_array($q, $tryAnyway = false, $params = [])
88
    {
89
        //debug?
90
        $debug = Config::inst()->get("GetLatLngFromGoogleUsingAddress", "debug");
91
        $q = trim($q);
92
        if ($q) {
93
            //check if we have searched for this before ...
94
            $result = null;
95
            $filter = array("SearchPhrase" => Convert::raw2sql($q));
96
            $searchRecord = DataObject::get_one(
97
                'GetLatLngFromGoogleUsingAddressSearchRecord',
98
                $filter,
99
                $cacheDataObjectGetOne = false
100
            );
101
            if ($searchRecord && $searchRecord->ResultArray) {
102
                if ($debug) {
103
                    debug::show("Results from GetLatLngFromGoogleUsingAddressSearchRecord");
104
                }
105
                //@ is important here!
106
                $result = @unserialize($searchRecord->ResultArray);
107
                //remove result if it can not be read
108
                if ($result === null) {
109
                    $searchRecord->ResultArray = "";
110
                    $searchRecord->write();
111
                }
112
                //return details if they seem correct ...
113
                elseif (isset($result["FullAddress"]) && isset($result["Longitude"]) && isset($result["Latitude"])) {
114
                    return $result;
115
                }
116
                $result = null;
117
            }
118
            if (!$result) {
119
                $result = self::get_placemark($q, $tryAnyway, $params);
120
                if ($debug) {
121
                    debug::show(print_r($result, 1));
122
                }
123
                if (is_object($result)) {
124
                    $resultArray = self::google_2_ss($result);
125
                    if ($debug) {
126
                        debug::show(print_r($resultArray, 1));
127
                    }
128
                    if (!$searchRecord) {
129
                        $searchRecord = GetLatLngFromGoogleUsingAddressSearchRecord::create($filter);
130
                    }
131
                    $searchRecord->ResultArray = serialize($resultArray);
132
                    $searchRecord->write();
133
                    return $resultArray;
134
                } else {
135
                    return array("FullAddress"=> "Could not find address");
136
                }
137
            }
138
        } else {
139
            return array("FullAddress"=> "No search term provided");
140
        }
141
    }
142
143
144
    /**
145
    * Get first placemark from google, or return false.
146
    *
147
    * @param string $q
148
    * @param bool $tryAnyway
149
    * @param array $params
150
    *
151
    * @return Object Single placemark | false
152
    */
153
    protected static function get_placemark($q, $tryAnyway = false, $params = [])
154
    {
155
        if (Config::inst()->get("GetLatLngFromGoogleUsingAddress", "server_side_available") || $tryAnyway) {
156
            $responseObj = self::get_geocode_obj($q, $params);
157
            if (Config::inst()->get("GetLatLngFromGoogleUsingAddress", "debug")) {
158
                debug::show(print_r($responseObj, 1));
159
            }
160
            if ($responseObj && $responseObj->status == 'OK' && isset($responseObj->results[0])) {
161
                //we just take the first address!
162
                if (Config::inst()->get("GetLatLngFromGoogleUsingAddress", "default_to_first_result") || count($responseObj->results) ==1) {
163
                    $result = $responseObj->results[0];
164
                    return $result;
165
                }
166
            }
167
        }
168
    }
169
170
171
    /**
172
        * Get geocode from google.
173
        *
174
        * @see http://code.google.com/apis/maps/documentation/services.html#Geocoding_Direct
175
        *
176
        * @param string $q Place name (e.g. 'Portland' or '30th Avenue, New York")
177
        * @param array $params any additional params for the cURL request.
178
        *
179
        * @return Object Multiple Placemarks and status code
0 ignored issues
show
Should the return type not be false|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
180
        */
181
    protected static function get_geocode_obj($q, $params = [])
182
    {
183
        $debug = Config::inst()->get("GetLatLngFromGoogleUsingAddress", "debug");
184
        $q = trim($q);
185
        if ($debug) {
186
            debug::show(print_r($q, 1));
187
        }
188
        if (empty($q)) {
189
            return false;
190
        }
191
        $url = sprintf(Config::inst()->get("GetLatLngFromGoogleUsingAddress", "geocode_url"), urlencode($q));
192
        if ($clientID = Config::inst()->get("GetLatLngFromGoogleUsingAddress", "google_client_id")) {
193
            $url .= "&client=".$clientID;
194
        } elseif ($api = Config::inst()->get("GetLatLngFromGoogleUsingAddress", "alternative_google_map_api_key")) {
195
            $url .= "&key=".$api;
196
        } elseif ($api = Config::inst()->get("GoogleMap", "google_map_api_key")) {
197
            $url .= "&key=".$api;
198
        }
199
        $params = $params + Config::inst()->get("GetLatLngFromGoogleUsingAddress", "additional_params");
200
        foreach ($params as $key => $value) {
201
            $url .= $key.'='.urlencode($value);
202
        }
203
        if ($debug) {
204
            debug::show(print_r($url, 1));
205
        }
206
        $ch = curl_init($url);
207
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
208
        curl_setopt($ch, CURLOPT_VERBOSE, true);
209
        $responseString = curl_exec($ch);
210
        curl_close($ch);
211
        if (!$responseString) {
212
            $responseString = file_get_contents($url);
213
            if (!$responseString) {
214
                return false;
215
            }
216
        }
217
218
        if ($debug) {
219
            debug::show(print_r($responseString, 1));
220
        }
221
222
        return self::json_decoder($responseString);
223
    }
224
225
    /**
226
     *
227
     * @param String (JSON)
228
     * @param Boolean $assoc
229
     *
230
     * @return Array
231
     */
232
    private static function json_decoder($content, $assoc = false)
0 ignored issues
show
The parameter $assoc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
233
    {
234
        return json_decode($content);
235
    }
236
237
    /**
238
     *
239
     * @param Array
240
     *
241
     * @return Array
0 ignored issues
show
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
242
     */
243
    private static function json_encoder($content)
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
244
    {
245
        return json_encode($content);
246
    }
247
248
    /**
249
     *
250
     *
251
GOOGLE:
252
    street_address indicates a precise street address.
253
    route indicates a named route (such as "US 101").
254
    intersection indicates a major intersection, usually of two major roads.
255
    political indicates a political entity. Usually, this type indicates a polygon of some civil administration.
256
    country indicates the national political entity, and is typically the highest order type returned by the Geocoder.
257
    administrative_area_level_1 indicates a first-order civil entity below the country level. Within the United States, these administrative levels are states. Not all nations exhibit these administrative levels.
258
    administrative_area_level_2 indicates a second-order civil entity below the country level. Within the United States, these administrative levels are counties. Not all nations exhibit these administrative levels.
259
    administrative_area_level_3 indicates a third-order civil entity below the country level. This type indicates a minor civil division. Not all nations exhibit these administrative levels.
260
    colloquial_area indicates a commonly-used alternative name for the entity.
261
    locality indicates an incorporated city or town political entity.
262
    sublocality indicates an first-order civil entity below a locality
263
    neighborhood indicates a named neighborhood
264
    premise indicates a named location, usually a building or collection of buildings with a common name
265
    subpremise indicates a first-order entity below a named location, usually a singular building within a collection of buildings with a common name
266
    postal_code indicates a postal code as used to address postal mail within the country.
267
    natural_feature indicates a prominent natural feature.
268
    airport indicates an airport.
269
    park indicates a named park.
270
    point_of_interest indicates a named point of interest. Typically, these "POI"s are prominent local entities that don't easily fit in another category such as "Empire State Building" or "Statue of Liberty."
271
272
    post_box indicates a specific postal box.
273
    street_number indicates the precise street number.
274
    floor indicates the floor of a building address.
275
    room indicates the room of a building address.
276
277
SS:
278
    'Latitude' => 'Double(12,7)',
279
    'Longitude' => 'Double(12,7)',
280
    'PointString' => 'Text',
281
    'Address' => 'Text',
282
    'FullAddress' => 'Text',
283
    'CountryNameCode' => 'Varchar(3)',
284
    'AdministrativeAreaName' => 'Varchar(255)',
285
    'SubAdministrativeAreaName' => 'Varchar(255)',
286
    'LocalityName' => 'Varchar(255)',
287
    'PostalCodeNumber' => 'Varchar(30)',
288
    */
289
290
    protected static $google_2_ss_translation_array = array(
291
        "administrative_area_level_1" => "AdministrativeAreaName",
292
        //two into one
293
        "locality" => "SubAdministrativeAreaName",
294
        "administrative_area_level_2" => "SubAdministrativeAreaName",
295
        //two into one!
296
        "sublocality" => "LocalityName",
297
        "locality" => "LocalityName",
298
        //two into one!
299
        "street_address" => "FullAddress",
300
        "formatted_address" => "FullAddress",
301
        //key ones
302
        "lng" => "Longitude",
303
        "lat" => "Latitude",
304
        "country" => "CountryNameCode",
305
        "postal_code" => "PostalCodeNumber"
306
    );
307
308
    /**
309
     * Converts Google Response INTO Silverstripe Google Map Array
310
     * that can be saved into a GoogleMapLocationsObject
311
     * @param GoogleResponseObject (JSON)
312
     * @return Array
313
     */
314
    protected static function google_2_ss($responseObj)
315
    {
316
        //get address parts
317
        $outputArray = array(
318
            "Original"=> $responseObj,
319
            "FullAddress"=> "Could not find address"
320
        );
321
        $translationArray = Config::inst()->get("GetLatLngFromGoogleUsingAddress", "google_2_ss_translation_array");
322
        if (isset($responseObj->address_components) && is_array($responseObj->address_components)) {
323
            foreach ($responseObj->address_components as $addressItem) {
324
                if (
325
                    is_object($addressItem)
326
                    && isset($addressItem->types)
327
                    && is_array($addressItem->types)
328
                    && count($addressItem->types)
329
                    && isset($addressItem->short_name)
330
                ) {
331
                    if (isset($translationArray[$addressItem->types[0]])) {
332
                        $outputArray[$translationArray[$addressItem->types[0]]] = $addressItem->short_name;
333
                    } else {
334
                        $outputArray[$addressItem->types[0]] = $addressItem->short_name;
335
                    }
336
                }
337
            }
338
        }
339
        if (!empty($responseObj->geometry) && !empty($responseObj->geometry->location)) {
340
            $outputArray["Longitude"] = $responseObj->geometry->location->lng;
341
            $outputArray["Latitude"] = $responseObj->geometry->location->lat;
342
            $outputArray["Accuracy"] = $responseObj->geometry->location_type;
343
        }
344
        //get other data
345
        if (!empty($responseObj->formatted_address)) {
346
            $outputArray["FullAddress"] = $responseObj->formatted_address;
347
        }
348
        return $outputArray;
349
    }
350
}
351