Issues (843)

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.

require/class.Common.php (3 issues)

Severity

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
 * This class is part of FlightAirmap. It's used for all common functions
4
 *
5
 * Copyright (c) Ycarus (Yannick Chabanois) <[email protected]>
6
 * Licensed under AGPL license.
7
 * For more information see: https://www.flightairmap.com/
8
*/
9
require_once(dirname(__FILE__).'/libs/simple_html_dom.php');
10
require_once(dirname(__FILE__).'/libs/uagent/uagent.php');
11
require_once(dirname(__FILE__).'/settings.php');
12
13
class Common {
14
	//protected $cookies = array();
15
	
16
	/**
17
	* Get data from form result
18
	* @param String $url form URL
19
	* @param String $type type of submit form method (get or post)
20
	* @param String|array $data values form post method
21
	* @param array $headers header to submit with the form
22
	* @return String the result
23
	*/
24
	public function getData($url, $type = 'get', $data = '', $headers = '',$cookie = '',$referer = '',$timeout = '',$useragent = '', $sizelimit = false, $async = false, $getheaders = false) {
25
		global $globalProxy, $globalForceIPv4;
26
		$ch = curl_init();
27
		curl_setopt($ch, CURLOPT_URL, $url);
28
		if (isset($globalForceIPv4) && $globalForceIPv4) {
29
			if (defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')){
30
				curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
31
			}
32
		}
33
		if (isset($globalProxy) && $globalProxy != '') {
34
			curl_setopt($ch, CURLOPT_PROXY, $globalProxy);
35
		}
36
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
37
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
38
		curl_setopt($ch, CURLINFO_HEADER_OUT, true); 
39
		if ($getheaders) curl_setopt($ch, CURLOPT_HEADER, 1); 
40
		curl_setopt($ch,CURLOPT_ENCODING , "gzip");
41
		//curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 GTB5');
42
//		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0');
43
		if ($useragent == '') {
44
			curl_setopt($ch, CURLOPT_USERAGENT, UAgent::random());
45
		} else {
46
			curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
47
		}
48
		if ($timeout == '') curl_setopt($ch, CURLOPT_TIMEOUT, 10); 
49
		else curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 
50
		//curl_setopt($ch, CURLOPT_HEADERFUNCTION, array('Common',"curlResponseHeaderCallback"));
51
		if ($type == 'post') {
52
			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
53
			if (is_array($data)) {
54
				curl_setopt($ch, CURLOPT_POST, count($data));
55
				$data_string = '';
56
				foreach($data as $key=>$value) { $data_string .= $key.'='.$value.'&'; }
57
				rtrim($data_string, '&');
58
				curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
59
			} else {
60
				curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
61
			}
62
		} elseif ($type != 'get' && $type != '') curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type);
63
		if ($headers != '') {
64
			curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
65
		}
66
		if ($cookie != '') {
67
			if (is_array($cookie)) {
68
				curl_setopt($ch, CURLOPT_COOKIE, implode($cookie,';'));
69
			} else {
70
				curl_setopt($ch, CURLOPT_COOKIE, $cookie);
71
			}
72
		}
73
		if ($referer != '') {
74
			curl_setopt($ch, CURLOPT_REFERER, $referer);
75
		}
76
		if ($sizelimit === true) {
77
			curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
78
			curl_setopt($ch, CURLOPT_NOPROGRESS, false);
79
			curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function($curlr,$downloadsize, $downloaded, $uploadsize, $uploaded){
0 ignored issues
show
The parameter $uploadsize 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...
The parameter $uploaded 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...
80
				return ($downloaded > (3*1024)) ? 1 : 0;
81
			});
82
		}
83
		if ($async) {
84
			curl_setopt($ch, CURLOPT_NOSIGNAL, 1); //to timeout immediately if the value is < 1000 ms
85
			curl_setopt($ch, CURLOPT_TIMEOUT_MS, 50);
86
		}
87
		$result = curl_exec($ch);
88
		$info = curl_getinfo($ch);
89
		//var_dump($info);
90
		curl_close($ch);
91
		if ($info['http_code'] == '503' && strstr($result,'DDoS protection by CloudFlare')) {
92
			echo "Cloudflare Detected\n";
93
			require_once(dirname(__FILE__).'/libs/cloudflare-bypass/libraries/cloudflareClass.php');
94
			$useragent = UAgent::random();
95
			cloudflare::useUserAgent($useragent);
96
			if ($clearanceCookie = cloudflare::bypass($url)) {
97
				return $this->getData($url,'get',$data,$headers,$clearanceCookie,$referer,$timeout,$useragent);
98
			}
99
		} else {
100
			return $result;
101
		}
102
	}
103
	
104
	private function curlResponseHeaderCallback($ch, $headerLine) {
0 ignored issues
show
The parameter $ch 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...
105
		global $curl_cookies;
106
		$curl_cookies = array();
107
		if (preg_match('/^Set-Cookie:\s*([^;]*)/mi', $headerLine, $cookie) == 1)
108
			$curl_cookies[] = $cookie;
109
		return strlen($headerLine); // Needed by curl
110
	}
111
112
113
	public static function download($url, $file, $referer = '', $headers = '') {
114
		global $globalDebug, $globalProxy, $globalForceIPv4;
115
		$fp = fopen($file, 'w');
116
		$ch = curl_init();
117
		curl_setopt($ch, CURLOPT_URL, $url);
118
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
119
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
120
		curl_setopt($ch, CURLOPT_COOKIEFILE, '');
121
		if ($referer != '') curl_setopt($ch, CURLOPT_REFERER, $referer);
122
		if (isset($globalForceIPv4) && $globalForceIPv4) {
123
			if (defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')){
124
				curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
125
			}
126
		}
127
		if ($headers != '') {
128
			curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
129
		}
130
		if (isset($globalProxy) && $globalProxy != '') {
131
			curl_setopt($ch, CURLOPT_PROXY, $globalProxy);
132
		}
133
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 GTB5');
134
		curl_setopt($ch, CURLOPT_FILE, $fp);
135
		curl_exec($ch);
136
		if (curl_errno($ch) && $globalDebug) echo 'Download error: '.curl_error($ch);
137
		curl_close($ch);
138
		fclose($fp);
139
	}
140
141
	public static function gunzip($in_file,$out_file_name = '') {
142
		//echo $in_file.' -> '.$out_file_name."\n";
143
		$buffer_size = 4096; // read 4kb at a time
144
		if ($out_file_name == '') $out_file_name = str_replace('.gz', '', $in_file); 
145
		if ($in_file != '' && file_exists($in_file)) {
146
			// PHP version of Ubuntu use gzopen64 instead of gzopen
147
			if (function_exists('gzopen')) $file = gzopen($in_file,'rb');
148
			elseif (function_exists('gzopen64')) $file = gzopen64($in_file,'rb');
149
			else {
150
				echo 'gzopen not available';
151
				die;
152
			}
153
			$out_file = fopen($out_file_name, 'wb'); 
154
			while(!gzeof($file)) {
155
				fwrite($out_file, gzread($file, $buffer_size));
156
			}  
157
			fclose($out_file);
158
			gzclose($file);
159
		}
160
	}
161
162
	public static function bunzip2($in_file,$out_file_name = '') {
163
		//echo $in_file.' -> '.$out_file_name."\n";
164
		$buffer_size = 4096; // read 4kb at a time
165
		if ($out_file_name == '') $out_file_name = str_replace('.bz2', '', $in_file); 
166
		if ($in_file != '' && file_exists($in_file)) {
167
			// PHP version of Ubuntu use gzopen64 instead of gzopen
168
			if (function_exists('bzopen')) $file = bzopen($in_file,'rb');
169
			else {
170
				echo 'bzopen not available';
171
				die;
172
			}
173
			$out_file = fopen($out_file_name, 'wb'); 
174
			while(!feof($file)) {
175
				fwrite($out_file, bzread($file, $buffer_size));
176
			}  
177
			fclose($out_file);
178
			bzclose($file);
179
		}
180
	}
181
182
	/**
183
	* Convert a HTML table to an array
184
	* @param String $data HTML page
185
	* @return array array of the tables in HTML page
186
	*/
187
	public function table2array($data) {
188
		if (!is_string($data)) return array();
189
		if ($data == '') return array();
190
		$html = str_get_html($data);
191
		if ($html === false) return array();
192
		$tabledata=array();
193
		foreach($html->find('tr') as $element)
194
		{
195
			$td = array();
196
			foreach( $element->find('th') as $row)
197
			{
198
				$td [] = trim($row->plaintext);
199
			}
200
			$td=array_filter($td);
201
			$tabledata[] = $td;
202
203
			$td = array();
204
			$tdi = array();
205
			foreach( $element->find('td') as $row)
206
			{
207
				$td [] = trim($row->plaintext);
208
				$tdi [] = trim($row->innertext);
209
			}
210
			$td=array_filter($td);
211
			$tdi=array_filter($tdi);
212
			$tabledata[]=array_merge($td,$tdi);
213
		}
214
		$html->clear();
215
		unset($html);
216
		return(array_filter($tabledata));
217
	}
218
	
219
	/**
220
	* Convert <p> part of a HTML page to an array
221
	* @param String $data HTML page
222
	* @return array array of the <p> in HTML page
223
	*/
224
	public function text2array($data) {
225
		$html = str_get_html($data);
226
		if ($html === false) return array();
227
		$tabledata=array();
228
		foreach($html->find('p') as $element)
229
		{
230
			$tabledata [] = trim($element->plaintext);
231
		}
232
		$html->clear();
233
		unset($html);
234
		return(array_filter($tabledata));
235
	}
236
237
	/**
238
	* Give distance between 2 coordonnates
239
	* @param Float $lat latitude of first point
240
	* @param Float $lon longitude of first point
241
	* @param Float $latc latitude of second point
242
	* @param Float $lonc longitude of second point
243
	* @param String $unit km else no unit used
244
	* @return Float Distance in $unit
245
	*/
246
	public function distance($lat, $lon, $latc, $lonc, $unit = 'km') {
247
		if ($lat == $latc && $lon == $lonc) return 0;
248
		$dist = rad2deg(acos(sin(deg2rad(floatval($lat)))*sin(deg2rad(floatval($latc)))+ cos(deg2rad(floatval($lat)))*cos(deg2rad(floatval($latc)))*cos(deg2rad(floatval($lon)-floatval($lonc)))))*60*1.1515;
249
		if ($unit == "km") {
250
			return round($dist * 1.609344);
251
		} elseif ($unit == "m") {
252
			return round($dist * 1.609344 * 1000);
253
		} elseif ($unit == "mile" || $unit == "mi") {
254
			return round($dist);
255
		} elseif ($unit == "nm") {
256
			return round($dist*0.868976);
257
		} else {
258
			return round($dist);
259
		}
260
	}
261
262
	/**
263
	* Give plunge between 2 altitudes and distance
264
	* @param Float $initial_altitude altitude of first point in m
265
	* @param Float $final_altitude altitude of second point in m
266
	* @param String $distance distance between two points in m
267
	* @return Float plunge
268
	*/
269
	public function plunge($initial_altitude,$final_altitude,$distance) {
270
		$plunge = rad2deg(asin(($final_altitude-$initial_altitude)/$distance));
271
		/*
272
		$siter = 6378137.0 + $initial_altitude;
273
		$planer = 6378137.0 + $final_altitude;
274
		$airdist = sqrt($siter-$siter + $planer*$planer - 2*$siter*$planer*cos($distance/6378137.0));
275
		echo 'airdist:'.$airdist;
276
		$plunge = rad2deg(asin(($planer*$planer - $siter*$siter - $airdist*$airdist)/(2*$siter+$distance)));
277
		*/
278
		return $plunge;
279
	}
280
281
	/**
282
	* Give azimuth between 2 coordonnates
283
	* @param Float $lat latitude of first point
284
	* @param Float $lon longitude of first point
285
	* @param Float $latc latitude of second point
286
	* @param Float $lonc longitude of second point
287
	* @return Float Azimuth
288
	*/
289
	public function azimuth($lat, $lon, $latc, $lonc) {
290
		$dX = $latc - $lat;
291
		$dY = $lonc - $lon;
292
		$azimuth = rad2deg(atan2($dY,$dX));
293
		if ($azimuth < 0) return $azimuth+360;
294
		return $azimuth;
295
	}
296
	
297
	
298
	/**
299
	* Check is distance realistic
300
	* @param int $timeDifference the time between the reception of both messages
301
	* @param float $distance distance covered
302
	* @return bool whether distance is realistic
303
	*/
304
	public function withinThreshold ($timeDifference, $distance) {
305
		$x = abs($timeDifference);
306
		$d = abs($distance);
307
		if ($x == 0 || $d == 0) return true;
308
		// may be due to Internet jitter; distance is realistic
309
		if ($x < 0.7 && $d < 2000) return true;
310
		else return $d/$x < 1500*0.27778; // 1500 km/h max
311
	}
312
313
314
	// Check if an array is assoc
315
	public function isAssoc($array)
316
	{
317
		return ($array !== array_values($array));
318
	}
319
320
	public function isInteger($input){
321
		//return(ctype_digit(strval($input)));
322
		return preg_match('/^-?[0-9]+$/', (string)$input) ? true : false;
323
	}
324
325
326
	public function convertDec($dms,$latlong) {
327
		if ($latlong == 'latitude') {
328
			$deg = substr($dms, 0, 2);
329
			$min = substr($dms, 2, 4);
330
		} else {
331
			$deg = substr($dms, 0, 3);
332
			$min = substr($dms, 3, 5);
333
		}
334
		return $deg+(($min*60)/3600);
335
	}
336
	
337
	public function convertDecLatLong($coord) {
338
		//N43°36.763' W5°46.845'
339
		$coords = explode(' ',$coord);
340
		$latitude = '';
341
		$longitude = '';
342
		foreach ($coords as $latlong) {
343
			$type = substr($latlong,0,1);
344
			$degmin = explode('°',substr($latlong,1,-1));
345
			$deg = $degmin[0];
346
			$min = $degmin[1];
347
			if ($type == 'N') {
348
				$latitude = $deg+(($min*60)/3600);
349
			} elseif ($type == 'S') {
350
				$latitude = -($deg+(($min*60)/3600));
351
			} elseif ($type == 'E') {
352
				$longitude = ($deg+(($min*60)/3600));
353
			} elseif ($type == 'W') {
354
				$longitude = -($deg+(($min*60)/3600));
355
			}
356
		}
357
		return array('latitude' => round($latitude,5),'longitude' => round($longitude,5));
358
	}
359
	
360
	public function convertDM($coord,$latlong) {
361
		if ($latlong == 'latitude') {
362
			if ($coord < 0) $NSEW = 'S';
363
			else $NSEW = 'N';
364
		} else {
365
			if ($coord < 0) $NSEW = 'W';
366
			else $NSEW = 'E';
367
		}
368
		$coord = abs($coord);
369
		$deg = floor($coord);
370
		$coord = ($coord-$deg)*60;
371
		$min = $coord;
372
		return array('deg' => $deg,'min' => $min,'NSEW' => $NSEW);
373
	}
374
	public function convertDMS($coord,$latlong) {
375
		if ($latlong == 'latitude') {
376
			if ($coord < 0) $NSEW = 'S';
377
			else $NSEW = 'N';
378
		} else {
379
			if ($coord < 0) $NSEW = 'W';
380
			else $NSEW = 'E';
381
		}
382
		$coord = abs($coord);
383
		$deg = floor($coord);
384
		$coord = ($coord-$deg)*60;
385
		$min = floor($coord);
386
		$sec = round(($coord-$min)*60);
387
		return array('deg' => $deg,'min' => $min,'sec' => $sec,'NSEW' => $NSEW);
388
	}
389
	
390
	/**
391
	* Copy folder contents
392
	* @param       string   $source    Source path
393
	* @param       string   $dest      Destination path
394
	* @return      bool     Returns true on success, false on failure
395
	*/
396
	public function xcopy($source, $dest)
397
	{
398
		$files = glob($source.'*.*');
399
		foreach($files as $file){
400
			$file_to_go = str_replace($source,$dest,$file);
401
			copy($file, $file_to_go);
402
		}
403
		return true;
404
	}
405
	
406
	/**
407
	* Check if an url exist
408
	* @param	String $url url to check
409
	* @return	bool Return true on succes false on failure
410
	*/
411
	public function urlexist($url){
412
		$headers=get_headers($url);
413
		return stripos($headers[0],"200 OK")?true:false;
414
	}
415
	
416
	/**
417
	* Convert hexa to string
418
	* @param	String $hex data in hexa
419
	* @return	String Return result
420
	*/
421
	public function hex2str($hex) {
422
		$str = '';
423
		$hexln = strlen($hex);
424
		for($i=0;$i<$hexln;$i+=2) $str .= chr(hexdec(substr($hex,$i,2)));
425
		return $str;
426
	}
427
	
428
	/**
429
	* Convert hexa color to rgb
430
	* @param	String $hex data in hexa
431
	* @return	String Return result
432
	*/
433
	public function hex2rgb($hex) {
434
		$hex = str_replace('#','',$hex);
435
		return sscanf($hex, "%02x%02x%02x"); 
436
	}
437
	
438
	public function getHeading($lat1, $lon1, $lat2, $lon2) {
439
		//difference in longitudinal coordinates
440
		$dLon = deg2rad($lon2) - deg2rad($lon1);
441
		//difference in the phi of latitudinal coordinates
442
		$dPhi = log(tan(deg2rad($lat2) / 2 + M_PI / 4) / tan(deg2rad($lat1) / 2 + M_PI / 4));
443
		//we need to recalculate $dLon if it is greater than pi
444
		if(abs($dLon) > M_PI) {
445
			if($dLon > 0) {
446
				$dLon = (2 * M_PI - $dLon) * -1;
447
			} else {
448
				$dLon = 2 * M_PI + $dLon;
449
			}
450
		}
451
		//return the angle, normalized
452
		return (rad2deg(atan2($dLon, $dPhi)) + 360) % 360;
453
	}
454
455
	public function checkLine($lat1,$lon1,$lat2,$lon2,$lat3,$lon3,$approx = 0.15) {
456
		//$a = ($lon2-$lon1)*$lat3+($lat2-$lat1)*$lon3+($lat1*$lon2+$lat2*$lon1);
457
		$a = -($lon2-$lon1);
458
		$b = $lat2 - $lat1;
459
		$c = -($a*$lat1+$b*$lon1);
460
		$d = $a*$lat3+$b*$lon3+$c;
461
		if ($d > -$approx && $d < $approx) return true;
462
		else return false;
463
	}
464
	
465
	public function array_merge_noappend() {
466
		$output = array();
467
		foreach(func_get_args() as $array) {
468
			foreach($array as $key => $value) {
469
				$output[$key] = isset($output[$key]) ?
470
				array_merge($output[$key], $value) : $value;
471
			}
472
		}
473
		return $output;
474
	}
475
	
476
477
	public function arr_diff($arraya, $arrayb) {
478
		foreach ($arraya as $keya => $valuea) {
479
			if (in_array($valuea, $arrayb)) {
480
				unset($arraya[$keya]);
481
			}
482
		}
483
		return $arraya;
484
	}
485
486
	/*
487
	* Check if a key exist in an array
488
	* Come from http://stackoverflow.com/a/19420866
489
	* @param Array array to check
490
	* @param String key to check
491
	* @return Bool true if exist, else false
492
	*/
493
	public function multiKeyExists(array $arr, $key) {
494
		// is in base array?
495
		if (array_key_exists($key, $arr)) {
496
			return true;
497
		}
498
		// check arrays contained in this array
499
		foreach ($arr as $element) {
500
			if (is_array($element)) {
501
				if ($this->multiKeyExists($element, $key)) {
502
					return true;
503
				}
504
			}
505
		}
506
		return false;
507
	}
508
	
509
	/**
510
	* Returns list of available locales
511
	*
512
	* @return array
513
	 */
514
	public function listLocaleDir()
515
	{
516
		$result = array('en');
517
		if (!is_dir('./locale')) {
518
			return $result;
519
		}
520
		$handle = @opendir('./locale');
521
		if ($handle === false) return $result;
522
		while (false !== ($file = readdir($handle))) {
523
			$path = './locale'.'/'.$file.'/LC_MESSAGES/fam.mo';
524
			if ($file != "." && $file != ".." && @file_exists($path)) {
525
				$result[] = $file;
526
			}
527
		}
528
		closedir($handle);
529
		return $result;
530
	}
531
532
	public function nextcoord($latitude, $longitude, $speed, $heading, $archivespeed = 1, $seconds = ''){
533
		global $globalMapRefresh;
534
		if ($seconds == '') {
535
			$distance = ($speed*0.514444*$globalMapRefresh*$archivespeed)/1000;
536
		} else {
537
			$distance = ($speed*0.514444*$seconds*$archivespeed)/1000;
538
		}
539
		$r = 6378;
540
		$latitude = deg2rad($latitude);
541
		$longitude = deg2rad($longitude);
542
		$bearing = deg2rad($heading); 
543
		$latitude2 =  asin( (sin($latitude) * cos($distance/$r)) + (cos($latitude) * sin($distance/$r) * cos($bearing)) );
544
		$longitude2 = $longitude + atan2( sin($bearing)*sin($distance/$r)*cos($latitude), cos($distance/$r)-(sin($latitude)*sin($latitude2)) );
545
		return array('latitude' => number_format(rad2deg($latitude2),5,'.',''),'longitude' => number_format(rad2deg($longitude2),5,'.',''));
546
	}
547
	
548
	public function getCoordfromDistanceBearing($latitude,$longitude,$bearing,$distance) {
549
		// distance in meter
550
		$R = 6378.14;
551
		$latitude1 = $latitude * (M_PI/180);
552
		$longitude1 = $longitude * (M_PI/180);
553
		$brng = $bearing * (M_PI/180);
554
		$d = $distance;
555
556
		$latitude2 = asin(sin($latitude1)*cos($d/$R) + cos($latitude1)*sin($d/$R)*cos($brng));
557
		$longitude2 = $longitude1 + atan2(sin($brng)*sin($d/$R)*cos($latitude1),cos($d/$R)-sin($latitude1)*sin($latitude2));
558
559
		$latitude2 = $latitude2 * (180/M_PI);
560
		$longitude2 = $longitude2 * (180/M_PI);
561
562
		$flat = round ($latitude2,6);
563
		$flong = round ($longitude2,6);
564
/*
565
		$dx = $distance*cos($bearing);
566
		$dy = $distance*sin($bearing);
567
		$dlong = $dx/(111320*cos($latitude));
568
		$dlat = $dy/110540;
569
		$flong = $longitude + $dlong;
570
		$flat = $latitude + $dlat;
571
*/
572
		return array('latitude' => $flat,'longitude' => $flong);
573
	}
574
575
	/**
576
	 * GZIPs a file on disk (appending .gz to the name)
577
	 *
578
	 * From http://stackoverflow.com/questions/6073397/how-do-you-create-a-gz-file-using-php
579
	 * Based on function by Kioob at:
580
	 * http://www.php.net/manual/en/function.gzwrite.php#34955
581
	 * 
582
	 * @param string $source Path to file that should be compressed
583
	 * @param integer $level GZIP compression level (default: 9)
584
	 * @return string New filename (with .gz appended) if success, or false if operation fails
585
	 */
586
	public function gzCompressFile($source, $level = 9){ 
587
		$dest = $source . '.gz'; 
588
		$mode = 'wb' . $level; 
589
		$error = false; 
590
		if ($fp_out = gzopen($dest, $mode)) { 
591
			if ($fp_in = fopen($source,'rb')) { 
592
				while (!feof($fp_in)) 
593
					gzwrite($fp_out, fread($fp_in, 1024 * 512)); 
594
				fclose($fp_in); 
595
			} else {
596
				$error = true; 
597
			}
598
			gzclose($fp_out); 
599
		} else {
600
			$error = true; 
601
		}
602
		if ($error)
603
			return false; 
604
		else
605
			return $dest; 
606
	} 
607
	
608
	public function remove_accents($string) {
609
		if ( !preg_match('/[\x80-\xff]/', $string) ) return $string;
610
		$chars = array(
611
		    // Decompositions for Latin-1 Supplement
612
		    chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
613
		    chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
614
		    chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
615
		    chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
616
		    chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
617
		    chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
618
		    chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
619
		    chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
620
		    chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
621
		    chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
622
		    chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
623
		    chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
624
		    chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
625
		    chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
626
		    chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
627
		    chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
628
		    chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
629
		    chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
630
		    chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
631
		    chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
632
		    chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
633
		    chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
634
		    chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
635
		    chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
636
		    chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
637
		    chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
638
		    chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
639
		    chr(195).chr(191) => 'y',
640
		    // Decompositions for Latin Extended-A
641
		    chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
642
		    chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
643
		    chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
644
		    chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
645
		    chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
646
		    chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
647
		    chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
648
		    chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
649
		    chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
650
		    chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
651
		    chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
652
		    chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
653
		    chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
654
		    chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
655
		    chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
656
		    chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
657
		    chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
658
		    chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
659
		    chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
660
		    chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
661
		    chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
662
		    chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
663
		    chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
664
		    chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
665
		    chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
666
		    chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
667
		    chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
668
		    chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
669
		    chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
670
		    chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
671
		    chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
672
		    chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
673
		    chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
674
		    chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
675
		    chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
676
		    chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
677
		    chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
678
		    chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
679
		    chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
680
		    chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
681
		    chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
682
		    chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
683
		    chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
684
		    chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
685
		    chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
686
		    chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
687
		    chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
688
		    chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
689
		    chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
690
		    chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
691
		    chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
692
		    chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
693
		    chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
694
		    chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
695
		    chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
696
		    chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
697
		    chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
698
		    chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
699
		    chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
700
		    chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
701
		    chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
702
		    chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
703
		    chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
704
		    chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
705
		);
706
		$string = strtr($string, $chars);
707
		return $string;
708
	}
709
	
710
	/*
711
	* Extract int from a string
712
	* Come from http://php.net/manual/fr/function.intval.php comment by michiel ed thalent nl
713
	*
714
	* @param String Input string
715
	* @return Integer integer from the string
716
	*/
717
	public function str2int($string, $concat = false) {
718
		$length = strlen($string);    
719
		for ($i = 0, $int = '', $concat_flag = true; $i < $length; $i++) {
720
			if (is_numeric($string[$i]) && $concat_flag) {
721
				$int .= $string[$i];
722
			} elseif(!$concat && $concat_flag && strlen($int) > 0) {
723
				$concat_flag = false;
724
			}
725
		}
726
		return (int) $int;
727
	}
728
	
729
	public function create_socket($host, $port, &$errno, &$errstr) {
730
		$ip = gethostbyname($host);
731
		$s = socket_create(AF_INET, SOCK_STREAM, 0);
732
		$r = @socket_connect($s, $ip, $port);
733
		if (!socket_set_nonblock($s)) echo "Unable to set nonblock on socket\n";
734
		if ($r || socket_last_error() == 114 || socket_last_error() == 115) {
735
			return $s;
736
		}
737
		$errno = socket_last_error($s);
738
		$errstr = socket_strerror($errno);
739
		socket_close($s);
740
		return false;
741
	}
742
743
	public function create_socket_udp($host, $port, &$errno, &$errstr) {
744
		$ip = gethostbyname($host);
745
		$s = socket_create(AF_INET, SOCK_DGRAM, 0);
746
		$r = @socket_bind($s, $ip, $port);
747
		if ($r || socket_last_error() == 114 || socket_last_error() == 115) {
748
			return $s;
749
		}
750
		$errno = socket_last_error($s);
751
		$errstr = socket_strerror($errno);
752
		socket_close($s);
753
		return false;
754
	}
755
756
	public function getUserIP() { 
757
		$client = @$_SERVER['HTTP_CLIENT_IP'];
758
		$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
759
		return filter_var($client, FILTER_VALIDATE_IP) ? $client : filter_var($forward, FILTER_VALIDATE_IP) ? $forward : $_SERVER['REMOTE_ADDR']; 
760
	}
761
	public function replace_mb_substr($string, $offset, $length)
762
	{
763
		if (!function_exists('mb_substr')) {
764
			$arr = preg_split("//u", $string);
765
			$slice = array_slice($arr, $offset + 1, $length);
766
			return implode("", $slice);
767
		} else {
768
			return mb_substr($string,$offset,$length,'UTF-8');
769
		}
770
	}
771
772
	// Come from comment : http://php.net/manual/fr/function.is-writable.php#73596
773
	public function is__writable($path) {
774
		//will work in despite of Windows ACLs bug
775
		//NOTE: use a trailing slash for folders!!!
776
		//see http://bugs.php.net/bug.php?id=27609
777
		//see http://bugs.php.net/bug.php?id=30931
778
		if ($path{strlen($path)-1}=='/') // recursively return a temporary file path
779
			return $this->is__writable($path.uniqid(mt_rand()).'.tmp');
780
		else if (is_dir($path))
781
			return $this->is__writable($path.'/'.uniqid(mt_rand()).'.tmp');
782
		// check tmp file for read/write capabilities
783
		$rm = file_exists($path);
784
		$f = @fopen($path, 'a');
785
		if ($f===false)
786
			return false;
787
		fclose($f);
788
		if (!$rm)
789
			unlink($path);
790
		return true;
791
	}
792
	
793
	/*
794
	 * Great circle route
795
	 * Translated to PHP from javascript version of https://github.com/springmeyer/arc.js
796
	 * @param Float $begin_lat Latitude of origin point
797
	 * @param Float $begin_lon Longitude of origin point
798
	 * @param Float $end_lat Latitude of final point
799
	 * @param Float $end_lon Longitude of final point
800
	 * @param Integer $nbpts Number of intermediate vertices desired
801
	 * @param Integer $offset Controls the likelyhood that lines will be split which cross the dateline
802
	 * @return Array Coordinate of the route
803
	*/
804
	public function greatcircle($begin_lat,$begin_lon,$end_lat,$end_lon,$nbpts = 20, $offset = 10) {
805
		if ($nbpts <= 2) return array(array($begin_lon,$begin_lat),array($end_lon,$end_lat));
806
		$sx = deg2rad($begin_lon);
807
		$sy = deg2rad($begin_lat);
808
		$ex = deg2rad($end_lon);
809
		$ey = deg2rad($end_lat);
810
		$w = $sx - $ex;
811
		$h = $sy - $ey;
812
		$z = pow(sin($h/2.0),2) + cos($sy)*cos($ey)*pow(sin($w/2.0),2);
813
		$g = 2.0*asin(sqrt($z));
814
		if ($g == M_PI || is_nan($g)) return array(array($begin_lon,$begin_lat),array($end_lon,$end_lat));
815
		$first_pass = array();
816
		$delta = 1.0/($nbpts-1);
817
		for ($i =0; $i < $nbpts; ++$i) {
818
			$step = $delta*$i;
819
			$A = sin((1 - $step) * $g) / sin($g);
820
			$B = sin($step * $g) / sin($g);
821
			$x = $A * cos($sy) * cos($sx) + $B * cos($ey) * cos($ex);
822
			$y = $A * cos($sy) * sin($sx) + $B * cos($ey) * sin($ex);
823
			$z = $A * sin($sy) + $B * sin($ey);
824
			$lat = rad2deg(atan2($z, sqrt(pow($x, 2) + pow($y, 2))));
825
			$lon = rad2deg(atan2($y, $x));
826
			$first_pass[] = array($lon,$lat);
827
		}
828
		$bHasBigDiff = false;
829
		$dfMaxSmallDiffLong = 0;
830
		// from http://www.gdal.org/ogr2ogr.html
831
		// -datelineoffset:
832
		// (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be splited)
833
		$dfDateLineOffset = $offset;
834
		$dfLeftBorderX = 180 - $dfDateLineOffset;
835
		$dfRightBorderX = -180 + $dfDateLineOffset;
836
		$dfDiffSpace = 360 - $dfDateLineOffset;
837
		
838
		// https://github.com/OSGeo/gdal/blob/7bfb9c452a59aac958bff0c8386b891edf8154ca/gdal/ogr/ogrgeometryfactory.cpp#L2342
839
		$first_pass_ln = count($first_pass);
840
		for ($j = 1; $j < $first_pass_ln; ++$j) {
841
			$dfPrevX = $first_pass[$j-1][0];
842
			$dfX = $first_pass[$j][0];
843
			$dfDiffLong = abs($dfX - $dfPrevX);
844
			if ($dfDiffLong > $dfDiffSpace &&
845
			    (($dfX > $dfLeftBorderX && $dfPrevX < $dfRightBorderX) || ($dfPrevX > $dfLeftBorderX && $dfX < $dfRightBorderX))) 
846
			{
847
				$bHasBigDiff = true;
848
			} else if ($dfDiffLong > $dfMaxSmallDiffLong) {
849
				$dfMaxSmallDiffLong = $dfDiffLong;
850
			}
851
		}
852
		$poMulti = array();
853
		$first_pass_ln = count($first_pass);
854
		if ($bHasBigDiff && $dfMaxSmallDiffLong < $dfDateLineOffset) {
855
			$poNewLS = array();
856
			//$poMulti[] = $poNewLS;
857
			for ($k = 0; $k < $first_pass_ln; ++$k) {
858
				$dfX0 = floatval($first_pass[$k][0]);
859
				if ($k > 0 &&  abs($dfX0 - $first_pass[$k-1][0]) > $dfDiffSpace) {
860
					$dfX1 = floatval($first_pass[$k-1][0]);
861
					$dfY1 = floatval($first_pass[$k-1][1]);
862
					$dfX2 = floatval($first_pass[$k][0]);
863
					$dfY2 = floatval($first_pass[$k][1]);
864
					if ($dfX1 > -180 && $dfX1 < $dfRightBorderX && $dfX2 == 180 &&
865
					    $k+1 < count($first_pass) &&
866
					    $first_pass[$k-1][0] > -180 && $first_pass[$k-1][0] < $dfRightBorderX)
867
					{
868
						$poNewLS[] = array(-180, $first_pass[$k][1]);
869
						$k++;
870
						//echo 'here';
871
						$poNewLS[] = array($first_pass[$k][0], $first_pass[$k][1]);
872
						continue;
873
					} else if ($dfX1 > $dfLeftBorderX && $dfX1 < 180 && $dfX2 == -180 &&
874
					    $k+1 < $first_pass_ln &&
875
					    $first_pass[$k-1][0] > $dfLeftBorderX && $first_pass[$k-1][0] < 180)
876
					{
877
						$poNewLS[] = array(180, $first_pass[$k][1]);
878
						$k++;
879
						$poNewLS[] = array($first_pass[$k][0], $first_pass[$k][1]);
880
						continue;
881
					}
882
					if ($dfX1 < $dfRightBorderX && $dfX2 > $dfLeftBorderX)
883
					{
884
						// swap dfX1, dfX2
885
						$tmpX = $dfX1;
886
						$dfX1 = $dfX2;
887
						$dfX2 = $tmpX;
888
						// swap dfY1, dfY2
889
						$tmpY = $dfY1;
890
						$dfY1 = $dfY2;
891
						$dfY2 = $tmpY;
892
					}
893
					if ($dfX1 > $dfLeftBorderX && $dfX2 < $dfRightBorderX) {
894
						$dfX2 += 360;
895
					}
896
					if ($dfX1 <= 180 && $dfX2 >= 180 && $dfX1 < $dfX2)
897
					{
898
						$dfRatio = (180 - $dfX1) / ($dfX2 - $dfX1);
899
						$dfY = $dfRatio * $dfY2 + (1 - $dfRatio) * $dfY1;
900
						$poNewLS[] = array($first_pass[$k-1][0] > $dfLeftBorderX ? 180 : -180, $dfY);
901
						$poMulti[] = $poNewLS;
902
						$poNewLS = array();
903
						$poNewLS[] = array($first_pass[$k-1][0] > $dfLeftBorderX ? -180 : 180, $dfY);
904
						//$poMulti[] = $poNewLS;
905
					} else {
906
						//$poNewLS[] = array();
907
						$poMulti[] = $poNewLS;
908
						$poNewLS = array();
909
					}
910
					$poNewLS[] = array($dfX0, $first_pass[$k][1]);
911
				} else {
912
					$poNewLS[] = array($first_pass[$k][0], $first_pass[$k][1]);
913
				}
914
			}
915
			$poMulti[] = $poNewLS;
916
		} else {
917
			// add normally
918
			$poNewLS0 = array();
919
			//$poMulti[] = $poNewLS0;
920
			for ($l = 0; $l < $first_pass_ln; ++$l) {
921
				$poNewLS0[] = array($first_pass[$l][0],$first_pass[$l][1]);
922
			}
923
			$poMulti[] = $poNewLS0;
924
		}
925
		return $poMulti;
926
	}
927
}
928
?>