forked from FreifunkFranken/VPNkeyXchange
-
Notifications
You must be signed in to change notification settings - Fork 0
/
function.php
262 lines (232 loc) · 6.98 KB
/
function.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
<?php
require_once "db.class.php";
require_once "pointLocation.class.php";
const hood_mysql_fields = '
ID as id,
name,
ESSID_AP as essid,
BSSID_MESH as mesh_bssid,
ESSID_MESH as mesh_essid,
ESSID_MESH as mesh_id,
protocol,
channel2,
mode2,
mesh_type2,
channel5,
mode5,
mesh_type5,
upgrade_path,
ntp_ip,
UNIX_TIMESTAMP(changedOn) as timestamp,
prefix, lat, lon
';
function debug($msg)
{
if (DEBUG) {
print_r($msg);
echo "\n";
}
}
/**
* returns details error msg (as json)
*
* @param integer $code HTTP error 400, 500 or 503
* @param string $msg Error message text
*/
function showError($code, $msg)
{
http_response_code($code);
header('Content-Type: application/json');
$errorObject = array('error' => array('msg' => $msg, 'url' => 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']));
print_r(json_encode($errorObject));
}
function sin_d($value)
{
return sin(deg2rad($value));
}
function cos_d($value)
{
return cos(deg2rad($value));
}
const EARTH_RADIUS = 6371;
/**
* Haversine distance function in km
* https://en.wikipedia.org/wiki/Haversine_formula
*
* @param double $lat1 latitude point 1
* @param double $lon1 longitude point 1
* @param double $lat2 latitude point 2
* @param double $lon2 longitude point 2
* @return integer distance between the points in km
*/
function distance_haversine($lat1, $lon1, $lat2, $lon2)
{
$alpha = ($lat1 - $lat2) * 0.5;
$beta = ($lon1 - $lon2) * 0.5;
$sin_alpha = sin_d($alpha);
$sin_beta = sin_d($beta);
$a = $sin_alpha * $sin_alpha + cos_d($lat1) * cos_d($lat2) * $sin_beta * $sin_beta;
$c = asin(min(1, sqrt($a)));
$distance = 2 * EARTH_RADIUS * $c;
return round($distance, 3);
}
/**
* Check if the given geo coordinates are within one of the hoods.
*
* @param double $lat latitude point 1
* @param double $lon longitude point 1
* @return array hood data
*/
function getHoodByGeo($lat, $lon)
{
$current_hood_dist = 99999999;
$best_result = array();
// load hoods from DB
try {
$q = 'SELECT '.hood_mysql_fields.' FROM hoods WHERE lat IS NOT NULL AND lon IS NOT NULL AND active=1;';
$rs = db::getInstance()->prepare($q);
$rs->execute();
} catch (PDOException $e) {
exit(showError(500, $e));
}
// check for every hood if it's nearer than the hood before
while ($result = $rs->fetch(PDO::FETCH_ASSOC)) {
debug("\n\nhood: " . $result['name'] . ', CenterLat: ' . $result['lat'] . ', hoodCenterLon: ' . $result['lon'] . ', hoodID: ' . $result['id']);
$distance = distance_haversine($result['lat'], $result['lon'], $lat, $lon);
debug('distance: $distance');
if ($distance <= $current_hood_dist) {
debug('Shorter distance found for hood ' . $result['id'] . '(' . $result['name'] . ')');
$current_hood_dist = $distance;
$best_result = $result;
}
}
return $best_result;
}
/**
* Get hood data based on KeyXchange ID.
*
* @param string $hoodid hood ID
* @return array hood data
*/
function getHoodById($hoodid)
{
// load hood from DB
try {
$q = 'SELECT '.hood_mysql_fields.' FROM hoods WHERE ID = :hoodid;';
$rs = db::getInstance()->prepare($q);
$rs->bindParam(':hoodid', $hoodid, PDO::PARAM_INT);
$rs->execute();
} catch (PDOException $e) {
exit(showError(500, $e));
}
return $rs->fetch(PDO::FETCH_ASSOC);
}
function getTrainstation()
{
return getHoodById(0);
}
function getAllVPNs($hoodId)
{
$ret = array();
// return all gateways in the hood
try {
$sql = "SELECT g.name, 'fastd' AS protocol, g.ip AS address, g.port, g.publickey AS 'key', g.contact
FROM gateways AS g WHERE hood_ID=:hood AND active=1;";
$rs = db::getInstance()->prepare($sql);
$rs->bindParam(':hood', $hoodId);
$rs->execute();
} catch (PDOException $e) {
exit(showError(500, $e));
}
while ($result = $rs->fetch(PDO::FETCH_ASSOC)) {
array_push($ret, $result);
}
return $ret;
}
function getPolyhoodsByHood()
{
try {
$rs = db::getInstance()->query("
SELECT polyhoods.polyid, lat, lon, hoodid
FROM polyhoods INNER JOIN polygons ON polyhoods.polyid = polygons.polyid
WHERE polyhoods.active=1
ORDER BY hoodid ASC, polyid ASC, ID ASC;
");
$rs->execute();
} catch (PDOException $e) {
exit(showError(500, $e));
}
$result = $rs->fetchall(PDO::FETCH_ASSOC);
$return = array();
foreach($result as $row) {
// one array of polygons per hood
if(!isset($return[$row['hoodid']])) {
$return[$row['hoodid']] = array();
}
// one array of vertices per polygon
if(!isset($return[$row['hoodid']][$row['polyid']])) {
$return[$row['hoodid']][$row['polyid']] = array();
}
$return[$row['hoodid']][$row['polyid']][] = array('lat' => floatval($row['lat']), 'lon' => floatval($row['lon']));
}
return $return;
}
function processPoly($point) {
$hood = array();
$pointLocation = new pointLocation();
// First only retrieve list of polyids
try {
$rc = db::getInstance()->prepare("
SELECT polyhoods.polyid, hoodid, MIN(polygons.lat) AS minlat, MIN(polygons.lon) AS minlon, MAX(polygons.lat) AS maxlat, MAX(polygons.lon) AS maxlon
FROM polyhoods INNER JOIN polygons ON polyhoods.polyid = polygons.polyid
INNER JOIN hoods ON hoods.ID = polyhoods.hoodid
WHERE hoods.active=1 AND polyhoods.active=1
GROUP BY polyid, hoodid
"); // This query will automatically exclude polyhoods being present in polyhoods table, but without vertices in polygons table
$rc->execute();
} catch (PDOException $e) {
exit(showError(500, $e));
}
// Set up all polygons, but do it without vertex coordinates
$polystore = array();
while($row = $rc->fetch(PDO::FETCH_ASSOC)) {
$polystore[$row['polyid']] = $row;
$polystore[$row['polyid']]['data'] = array(); // prepare array for vertex coordinates
}
// Now query the coordinates, all in one query
try {
$rc = db::getInstance()->prepare("SELECT polyid, lat, lon FROM polygons ORDER BY ID ASC");
$rc->execute();
} catch (PDOException $e) {
exit(showError(500, $e));
}
// Write polygon coordinates into array
while($row = $rc->fetch(PDO::FETCH_ASSOC)) {
if(!isset($polystore[$row['polyid']])) {
debug('Database inconsistent: No polyhood defined for ID '.$row['polyid']);
continue; // Skip those orphaned vertex entries
}
$polystore[$row['polyid']]['data'][] = array(floatval($row["lon"]),floatval($row["lat"]));
debug('lon: '.$row["lon"].' lat: '.$row["lat"]);
}
// Interpret polygon data
foreach($polystore as $polygon) {
// First check whether point coordinates are outside the most extreme values for lat/lng
$exclude = $pointLocation->excludePolygon($point, $polygon['minlon'], $polygon['maxlon'], $polygon['minlat'], $polygon['maxlat']);
if ($exclude) {
debug("polygon #" . $polygon['polyid'] . " excluded<br>");
continue;
}
// Now really check whether point is inside polygon
$polygon['data'][] = $polygon['data'][0]; // Add first point as last point (= close polygon)
$inside = $pointLocation->pointInPolygon($point, $polygon['data']);
debug("point in polygon #" . $polygon['polyid'] . ": " . $inside . "<br>");
if ($inside) {
debug("PolyHood gefunden...");
$hood = getHoodById($polygon['hoodid']);
break;
}
}
return $hood;
}
?>