Completed
Push — master ( 589edc...c24ce2 )
by Yannick
35:38
created

Common::getData()   F

Complexity

Conditions 25
Paths > 20000

Size

Total Lines 78
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 60
nc 27648
nop 11
dl 0
loc 78
rs 2.3445
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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