Database Signage BRIGADOON-0012
Update Signage in Open Simulator from Database
Loading...
Searching...
No Matches
teleport.php
Go to the documentation of this file.
1<?php
2
20
21// Passwords for the database are stored outside of the webserver accessible directories to improve security.
22// Ensure that passwor file has the correct permission to read, but not be written.
23include '/usr/local/share/brigadoon/apache/os_passwords.php';
24
42 function rdConfirmUser($UseSimDb, $PDO, $PDO1)
43 {
44 global $remote_world; global $teleport_allowed; global $readings;
45
46 $not_known = TRUE;
47
48 //============================================================================
49 // If the Simulator Database is available, confirm the teleporter owner is known
50 //============================================================================
51 if ($UseSimDb)
52 {
53 $sql_query = "select PrincipalId from UserAccounts where PrincipalId = :key";
54 $stmt = $PDO1->prepare($sql_query);
55 $stmt->execute(['key' => $readings['owner']]);
56 $is_user = $stmt->fetch(PDO::FETCH_ASSOC);
57 if ($is_user)
58 {
59 $not_known = FALSE;
60 }
61 }
62
63 //============================================================
64 // Check if the User is in the Support Allowed Table
65 //============================================================
66 if ($not_known)
67 {
68 $sql_query = "select * from ls_os_teleport_allowed where teleport_owner = :key and teleport_world = :world";
69 $stmt = $PDO->prepare($sql_query);
70 $stmt->execute(['key' => $readings['owner'], 'world' => $readings['world']]);
71 $is_user = $stmt->fetch(PDO::FETCH_ASSOC);
72 if (!$is_user)
73 {
74 die("FAILURE=BANNED|Teleporter Owner ". $readings['owner']. " is unknown\n");
75 }
76 else
77 {
78 $remote_world = $is_user['teleport_world'];
79 $is_allowed = $is_user['teleport_allowed'];
80 }
81 }
82 }
83
84 //#############################################################################################################
85 //# OPEN A DATABASE
86 //#############################################################################################################
99 function rdOpenDatabase($Database, $Host, $Username, $Password)
100 {
101 // Data Source Name (DSN) string
102 $dsn = "mysql:host=$Host;dbname=$Database;charset=utf8mb4";
103
104 // Set PDO options for better error handling and security
105 $options = [
106 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Throw exceptions on errors
107 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Set default fetch mode to associative array
108 PDO::ATTR_EMULATE_PREPARES => true, // Disable emulated prepares for better security
109 ];
110
111 try
112 {
113 // Create a new PDO connection instance
114 $pdo = new PDO($dsn, $Username, $Password, $options);
115 }
116 catch (PDOException $e)
117 {
118 // Catch the exception and display a user-friendly error message
119 // In a production environment, you might log the specific error
120
121 die("FAILURE=DATABASE:Connection failed " . $e->getMessage());
122 }
123
124 return $pdo;
125 }
126
127 //#################################################################################
128 //#################################################################################
129 //## Program Entry ##
130 //#################################################################################
131 //#################################################################################
142 public function rdProcessTeleport()
143 {
144 global $readings;
145
146 //=================================================================================
147 // Initialise Constants and Pre-set Variables
148 //=================================================================================
149
150 // Define what a NULL KEY actually is.
151 $NULL_KEY = (string)'00000000-0000-0000-0000-000000000000';
152
153 $pdo; $pdo1;
154 $remote_world = "";
155 $teleport_allowed = FALSE;
156
157 //=================================================================================
158 //= Define if the Simulator's working databse will be accessed
159 //=================================================================================
160 $use_sim_db = TRUE;
161
162 //=================================================================================
163 // Set whether addresses outside of the home world of this program are allowed
164 //=================================================================================
165 // If this value is set to FALSE, teleporters out side of the home world of this
166 // simulator are not allowed to access the database.
167 //=================================================================================
168 $allow_outsiders = FALSE;
169
170 //=================================================================================
171 // Connect to the Required Databases
172 //=================================================================================
173
174 global $db; global $host; global $db_username; global $db_password;
175 global $db1; global $host1; global $db1_username; global $db1_password;
176 global $pdo; global $pdo1; global $remote_world; global $readings;
177
178 // Connect to the Support Database
179 $pdo = $this->rdOpenDatabase($db, $host, $db_username, $db_password);
180
181 // Connect to the Simulator's database if it is to be used
182
183 if ($use_sim_db) $pdo1 = $this->rdOpenDatabase($db1, $host1, $db1_username, $db1_password);
184
185
186 //==================================================================================
187 // Confirnm the User & Get World and Permission
188 //==================================================================================
189
190 $this->rdConfirmUser($use_sim_db, $pdo, $pdo1);
191
192 //=================================================================================
193 // Check if this is a Heartbeat Command
194 //=================================================================================
195
196 // Process the Parameters if the Command is "heartbeat"
197 if ($readings['command'] == "heartbeat")
198 {
199 //##############################################################################
200 //# Determine if External Worlds are Allowed to Access the Teleporter Dataabse #
201 //##############################################################################
202 if ($remote_world != "" && (!is_allowed || !$allow_outsiders))
203 {
204 die("FAILURE=BANNED|Teleporter Owner ". $readings['owner']. "@".$readings['world']." is not authorised\n");
205 }
206
207 //############################################################################
208 //# Decode the Array Information that has been pass in. #
209 //############################################################################
210
211 // Decode the Position array into the $position array. 0->x, 1->y, 2->z
212 $position_string = substr($readings['position'], 1, -1); // Remove leading and trailing angle brackets
213 $pos = explode(",", $position_string);
214 $position = array_slice($pos, 0, 3);
215
216 // Decode the Rotation into the rotation array. 0->x, 1->y, 2->z, 3->s
217 $rotation_string = substr($readings['rotation'], 1, -1); // Remove leading and trailing angle breackets
218 $rot = explode(",", $rotation_string);
219 $rotation = array_slice($rot, 0, 4);
220
221 //###################################################################
222 //# Determine if this teleporter is already known #
223 //###################################################################
224
225 // Determine if this heartbeat is from an already known Teleporter
226 $sql_query = "select * from ls_os_teleport where teleport_key = :key";
227 try
228 {
229 $stmt = $pdo->prepare($sql_query);
230 $stmt->execute(['key' => $readings['key']]);
231 $exists = $stmt->fetch(PDO::FETCH_ASSOC);
232 }
233 catch (Exception $e)
234 {
235 echo "FAILURE=IDENTIFY:".$e->getMessage()."\n";
236 }
237
238 //###################################################################
239 //# If this entry is found, then this just an update #
240 //###################################################################
241 if ($exists)
242 {
243 // Get the Substitution Fields
244 $data =
245 [
246 $readings['name'], $readings['owner'], $readings['world'], $readings['region'],
247 $position[0], $position[1], $position[2],
248 $rotation[0], $rotation[1], $rotation[2], $rotation[3],
249 $readings['offset'], $readings['group'], $readings['offsetangle'],
250 $readings['locationinfo'], $readings['vernum'], $readings['localitygroup'],
251 $readings['key']
252 ];
253
254 // Create the command to run to make the update
255 $sql_query = "update ls_os_teleport set ";
256 $sql_query .= "teleport_name = ?, teleport_owner_key = ?, teleport_world = ?, teleport_region = ?, ";
257 $sql_query .= "teleport_region_x = ?, teleport_region_y = ?, teleport_region_z = ?, ";
258 $sql_query .= "teleport_rotation_x = ?, teleport_rotation_y = ?, teleport_rotation_z = ?, teleport_rotation_s = ?, ";
259 $sql_query .= "teleport_offset = ?, teleport_group_key = ?, teleport_front_offset_angle = ?, ";
260 $sql_query .= "teleport_location_info = ?, teleport_version_number = ?, teleport_locality_group = ?, ";
261 $sql_query .= "teleport_heartbeat = CURRENT_TIMESTAMP()";
262 $sql_query .= "where teleport_key = ?";
263
264 // Attempt to Update the Database Entry for this Teleporter
265 try
266 {
267 $stmt = $pdo->prepare($sql_query);
268 $stmt->execute($data);
269 }
270 catch (Exception $e)
271 {
272 echo "FAILURE=UPDATE:".$e->getMessage()."\n";
273 }
274 }
275
276 //###################################################################
277 //# If it wasn't Found, It is a new Teleporter #
278 //###################################################################
279 else
280 {
281 // Test to see if this new item has an name that already exists in the database.
282 // Duplicate name are not permitted to prevent tue users becoming confused. If it
283 // is a duplicate, send a warning that there is a name violation to the owner of
284 // this new teleporter.
285
286 $sql_query = "select * from ls_os_teleport where teleport_name = :name";
287 try
288 {
289 $stmt = $pdo->prepare($sql_query);
290 $stmt->execute(['name' => $readings['name']]);
291 $same_name = $stmt->fetch(PDO::FETCH_ASSOC);
292 }
293 catch (Exception $e)
294 {
295 echo "FAILURE=NAME_MATCH: ".$readings['name'].":Failed with".$e->getMessage()."\n";
296 }
297 if ($same_name)
298 {
299 echo "FAILURE=NAME_MATCH: Existing teleporter data - ";
300 echo $row['teleport_world']."/".$row['teleport_region']."/";
301 echo "<".$row['teleport_region_x'].",".$row['teleport_region_y'].",".$row['teleport_region_z'].">\n";
302 }
303 else
304 {
305 // Get the Substitution Fields
306 $data =
307 [
308 $readings['key'], $readings['name'], $readings['owner'], $readings['world'], $readings['region'],
309 $position[0], $position[1], $position[2],
310 $rotation[0], $rotation[1], $rotation[2], $rotation[3],
311 $readings['offset'], $readings['group'], $readings['offsetangle'],
312 $readings['locationinfo'], $readings['vernum'], $readings['localitygroup']
313 ];
314
315 // Create the command to run to make the insert
316 $sql_query = "insert into ls_os_teleport(";
317 $sql_query .= "teleport_key, teleport_name, teleport_owner_key, teleport_world, teleport_region, ";
318 $sql_query .= "teleport_region_x, teleport_region_y, teleport_region_z, ";
319 $sql_query .= "teleport_rotation_x, teleport_rotation_y, teleport_rotation_z, teleport_rotation_s, ";
320 $sql_query .= "teleport_offset, teleport_group_key, teleport_front_offset_angle,";
321 $sql_query .= "teleport_location_info, teleport_version_number, teleport_locality_group";
322 $sql_query .= ")VALUES(";
323 $sql_query .= "?, ?, ?, ?, ?, ";
324 $sql_query .= "?, ?, ?, ";
325 $sql_query .= "?, ?, ?, ?, ";
326 $sql_query .= "?, ?, ?, ";
327 $sql_query .= "?, ?, ?";
328 $sql_query .= ")";
329
330 // Attempt to Update the Database Entry for this Teleporter
331 try
332 {
333 $stmt = $pdo->prepare($sql_query);
334 $stmt->execute($data);
335 }
336 catch (Exception $e)
337 {
338 echo "FAILURE=INSERT:".$e->getMessage()."\n";
339 }
340 }
341 }
342
343 // Send the Message Preamble
344 echo "EXTRACT_LIST=START\n";
345
346 // Isolate the Individual Flags from the location information
347 $this_group_flag = $readings['locationinfo'] & $GROUP_FLAG;
348 $this_region_flag = $readings['locationinfo'] & $REGION_FLAG;
349 $this_world_flag = $readings['locationinfo'] & $WORLD_FLAG;
350 $this_metaverse_flag = $readings['locationinfo'] & $METAVERSE_FLAG;
351
352 $sql_query = "";
353
354 // Depending on the options selected in the LOCATION_TYPES in the configuration file, this query will
355 // make a selection destinations in the region holding the Teleporter. LOCAL will select all destinations
356 // that have a LOCALITY_GROUP that matches the LOCALITY_GROUP value.
357 $sql_query .= "select * from ls_os_teleport";
358 $sql_query .= " where teleport_key != :key";
359 $sql_query .= " and ((teleport_location_info & :group_flag = :this_group_flag and teleport_locality_group = :group) or teleport_location_info & :region_flag = :this_region_flag)";
360 $sql_query .= " and teleport_location_info & :anon_flag = 0";
361 $sql_query .= " and teleport_region = :region";
362 $sql_query .= " and teleport_world = :world";
363 $sql_query .= " and teleport_version_number != 0";
364
365 $sql_query .= " UNION ";
366
367 // Check if this s a World or Meteverse Location
368 $sql_query .= "select * from ls_os_teleport ";
369 $sql_query .= " where teleport_key != :key";
370 $sql_query .= " and ((teleport_location_info & :world_flag = :this_world_flag and teleport_world = :world)";
371 $sql_query .= " and teleport_location_info & :anon_flag = 0";
372 $sql_query .= " or (teleport_location_info & :metaverse_flag = :this_metaverse_flag and teleport_world != :world))";
373 $sql_query .= " and teleport_version_number != 0";
374
375 // Sort the Responses into Alphbetical Order
376 $sql_query .= " order by teleport_name";
377
378 $parameters = [
379 'key' => $readings['key'],
380 'group_flag' => $GROUP_FLAG,
381 'region_flag' => $REGION_FLAG,
382 'world_flag' => $WORLD_FLAG,
383 'metaverse_flag' => $METAVERSE_FLAG,
384 'anon_flag' => $ANONYMOUS_FLAG,
385 'this_group_flag' => $this_group_flag,
386 'this_region_flag' => $this_region_flag,
387 'this_world_flag' => $this_world_flag,
388 'this_metaverse_flag' => $this_metaverse_flag,
389 'group' => $readings['localitygroup'],
390 'region'=> $readings['region'],
391 'world' => $readings['world']
392 ];
393
394 $this->rdSelectDestinations($sql_query, $parameters, $pdo, $readings['world'], $readings['region']);
395
396 // Send the Message Postamble
397 sleep(1);
398 echo "EXTRACT_LIST=END\n";
399 }
400
401 // If the Command is a Scan, Process the Destination Entries in the Support Database
402 if ($readings['command'] == "scan")
403 {
404
405 //#############################################################################
406 //## Scan the Contents of the Destinations for recent Heartbeats ##
407 //#############################################################################
408 // Remove the Teleporter if they havw exceeded their lifetime without sending
409 // a heartbeat message. Destinations that did not come from a Teleporter, that
410 // manually entered are not affected by this process, but are identified as
411 //being past End Of Life (EOL).
412
413 $world = $readings['world'];
414
415 $SqlQuery = "select * from ls_os_teleport";
416 $SqlQuery .= "where DATE_ADD(teleport_heartbeat, INTERVAL :lifetime HOUR) < CURRENT_TIMESTAMP()";
417 $SqlQuery .= " and teleport_version_number != 0 ";
418 if ($world != '###') $SqlQuery .= " and teleport_world = :world";
419 $SqlQuery .= " order by teleport_name;";
420
421 $Parameters = ['lifetime' => $readings['lifetime'] ];
422 if ($world != '###') $Parameters['world'] = $world;
423
424 try
425 {
426 $stmt = $pdo->prepare($SqlQuery);
427 $stmt->execute($Parameters);
428 $results = $stmt->fetchAll(PDO::FETCH_DEFAULT);
429 }
430 catch (Exception $e)
431 {
432 echo "FAILURE=SCAN:".$e->getMessage()."\n";
433 }
434
435 //#########################################################################################
436 //# Process Each Line #
437 //#########################################################################################
438
439 echo "SCAN_LIST=START\n";
440 echo "//=========================== Date: ".date("Y-m-d H:i:s")."==================\n";
441
442 foreach ($results as $row)
443 {
444 $action_string = "SCANNED";
445 $teleport_name = $row['teleport_name'];
446 $teleport_version = $row['teleport_version_number'];
447
448 // If OnlyScn is FALSE, delete the teleporter from the teleporter table
449 if ($readings['onlyscan'] == 0)
450 {
451 $sql_query1 = "delete from ls_os_teleport where teleport_key = :key";
452 $parameters1 = ['key' => $row['teleport_key'] ];
453 $stmt1 = $pdo->prepare($sql_query1);
454 $stmt1->execute($parameters1);
455 $results1 = $stmt1->fetchAll(PDO::FETCH_DEFAULT);
456 $action_string = "DELETED";
457 }
458 echo $row['teleport_name']."|".$action_string."|";
459 echo "hop://".$row['teleport_world']."/".$row['teleport_region']."/".$row['teleport_region_x']."/".$row['teleport_region_y']."/".$row['teleport_region_z']."\n";
460 }
461 echo "SCAN_LIST=END\n";
462 }
463 }
464}
465
466//=================================================================================
467// Initialise the Parameters from the URL
468//=================================================================================
469
470// Get the Parameters passed to the Program and Decode them
471$parameters = json_encode($_GET);
472$readings = json_decode( $parameters, true );
473
474$my_teleport = new rdTeleport();
475$my_teleport->rdProcessTeleport();
476
477?>
478
$readings
Definition teleport.php:472
rdProcessTeleport()
The public function that does all the work.
Definition teleport.php:142
rdOpenDatabase($Database, $Host, $Username, $Password)
Open the Support Database for Use.
Definition teleport.php:99
$my_teleport
Definition teleport.php:474
$parameters
Definition teleport.php:471
rdConfirmUser($UseSimDb, $PDO, $PDO1)
Fucntion to confirm that the object's owner is authorise to run script.
Definition teleport.php:42