Database Teleporter BRIGADOON-0009
An Open Simulator Teleporter using a central 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
25
31{
44 function rdSelectDestinations($SqlQuery, $Parameters, $Pdo, $ThisWorld, $ThisRegion)
45 {
46 try
47 {
48 $stmt = $Pdo->prepare($SqlQuery);
49 $stmt->execute($Parameters);
50 $results = $stmt->fetchAll(PDO::FETCH_DEFAULT);
51
52 //#########################################################################################
53 //# Process Each Line #
54 //#########################################################################################
55
56 if ($results)
57 {
58
59 foreach ($results as $row)
60 {
61 $result_world = $row['teleport_world']; $result_region = $row['teleport_region'];
62
63 echo $row['teleport_name']."|";
64 echo "<".$row['teleport_region_x'].",".$row['teleport_region_y'].",".$row['teleport_region_z'].">|";
65 echo "<".$row['teleport_rotation_x'].",".$row['teleport_rotation_y'].",".$row['teleport_rotation_z'].",".$row['teleport_rotation_s'].">|";
66 echo "<".$row['teleport_offset'].",".$row['teleport_front_offset_angle'].",".$row['teleport_location_info'].">|";
67 echo $row['teleport_locality_group']."|";
68
69 // Check if the Full Address is Needed
70 if ($result_world != $ThisWorld)
71 {
72 $location_type = 2;
73 echo $location_type."|";
74 echo $result_region."|".$result_world."\n";
75 }
76 else if ($result_region != $ThisRegion)
77 {
78 $location_type = 1;
79 echo $location_type."|";
80 echo $result_region."\n";
81 }
82 else
83 {
84 $location_type = 0;
85 echo $location_type."\n";
86 }
87 }
88 }
89 }
90 catch (Exception $e)
91 {
92 echo("FAILURE=EXTRACT:".$e->getMessage()."\n");
93 }
94 }
95
113 function rdConfirmUser($UseSimDb, $PDO, $PDO1)
114 {
115 global $remote_world; global $teleport_allowed; global $readings;
116
117 $not_known = TRUE;
118
119 //============================================================================
120 // If the Simulator Database is available, confirm the teleporter owner is known
121 //============================================================================
122 if ($UseSimDb)
123 {
124 $sql_query = "select PrincipalId from UserAccounts where PrincipalId = :key";
125 $stmt = $PDO1->prepare($sql_query);
126 $stmt->execute(['key' => $readings['owner']]);
127 $is_user = $stmt->fetch(PDO::FETCH_ASSOC);
128 if ($is_user)
129 {
130 $not_known = FALSE;
131 }
132 }
133
134 //============================================================
135 // Check if the User is in the Support Allowed Table
136 //============================================================
137 if ($not_known)
138 {
139 $sql_query = "select * from ls_os_teleport_allowed where teleport_owner = :key and teleport_world = :world";
140 $stmt = $PDO->prepare($sql_query);
141 $stmt->execute(['key' => $readings['owner'], 'world' => $readings['world']]);
142 $is_user = $stmt->fetch(PDO::FETCH_ASSOC);
143 if (!$is_user)
144 {
145 die("FAILURE=BANNED|Teleporter Owner ". $readings['owner']. " is unknown\n");
146 }
147 else
148 {
149 $remote_world = $is_user['teleport_world'];
150 $is_allowed = $is_user['teleport_allowed'];
151 }
152 }
153 }
154
155 //#############################################################################################################
156 //# OPEN A DATABASE
157 //#############################################################################################################
170 function rdOpenDatabase($Database, $Host, $Username, $Password)
171 {
172 // Data Source Name (DSN) string
173 $dsn = "mysql:host=$Host;dbname=$Database;charset=utf8mb4";
174
175 // Set PDO options for better error handling and security
176 $options = [
177 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Throw exceptions on errors
178 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Set default fetch mode to associative array
179 PDO::ATTR_EMULATE_PREPARES => true, // Disable emulated prepares for better security
180 ];
181
182 try
183 {
184 // Create a new PDO connection instance
185 $pdo = new PDO($dsn, $Username, $Password, $options);
186 }
187 catch (PDOException $e)
188 {
189 // Catch the exception and display a user-friendly error message
190 // In a production environment, you might log the specific error
191
192 die("FAILURE=DATABASE:Connection failed " . $e->getMessage());
193 }
194
195 return $pdo;
196 }
197
198 //#################################################################################
199 //#################################################################################
200 //## Program Entry ##
201 //#################################################################################
202 //#################################################################################
213 public function rdProcessTeleport()
214 {
215 global $readings;
216
217 //=================================================================================
218 // Initialise Constants and Pre-set Variables
219 //=================================================================================
220
221 // Define what a NULL KEY actually is.
222 $NULL_KEY = (string)'00000000-0000-0000-0000-000000000000';
223
224 // Initialise the List of Teleport Destinations
225 $teleporter = [];
226
227 $allow_outsiders = FALSE;
228
229 $LOCAL_LOCATION = "GROUP";
230 $REGION_LOCATION = "REGION";
231 $WORLD_LOCATION = "WORLD";
232 $METAVERSE_LOCATION = "METAVERSE";
233
234 $GROUP_FLAG = 1;
235 $REGION_FLAG = 2;
236 $WORLD_FLAG = 4;
237 $METAVERSE_FLAG = 8;
238
239 $LOCATION_MASK = $GROUP_FLAG | $REGION_FLAG | $WORLD_FLAG | $METAVERSE_FLAG;
240
241 $ANONYMOUS_FLAG = 16;
242
243 $pdo; $pdo1;
244 $remote_world = "";
245 $teleport_allowed = FALSE;
246
247 //=================================================================================
248 //= Define if the Simulator's working databse will be accessed
249 //=================================================================================
250 $use_sim_db = TRUE;
251
252 //=================================================================================
253 // Set whether addresses outside of the home world of this program are allowed
254 //=================================================================================
255 // If this value is set to FALSE, teleporters out side of the home world of this
256 // simulator are not allowed to access the database.
257 //=================================================================================
258 $allow_outsiders = FALSE;
259
260 //=================================================================================
261 // Connect to the Required Databases
262 //=================================================================================
263
264 global $db; global $host; global $db_username; global $db_password;
265 global $db1; global $host1; global $db1_username; global $db1_password;
266 global $pdo; global $pdo1; global $remote_world; global $readings;
267
268 // Connect to the Support Database
269 $pdo = $this->rdOpenDatabase($db, $host, $db_username, $db_password);
270
271 // Connect to the Simulator's database if it is to be used
272
273 if ($use_sim_db) $pdo1 = $this->rdOpenDatabase($db1, $host1, $db1_username, $db1_password);
274
275
276 //==================================================================================
277 // Confirnm the User & Get World and Permission
278 //==================================================================================
279
280 $this->rdConfirmUser($use_sim_db, $pdo, $pdo1);
281
282 //=================================================================================
283 // Check if this is a Heartbeat Command
284 //=================================================================================
285
286 // Process the Parameters if the Command is "heartbeat"
287 if ($readings['command'] == "heartbeat")
288 {
289 //##############################################################################
290 //# Determine if External Worlds are Allowed to Access the Teleporter Dataabse #
291 //##############################################################################
292 if ($remote_world != "" && (!is_allowed || !$allow_outsiders))
293 {
294 die("FAILURE=BANNED|Teleporter Owner ". $readings['owner']. "@".$readings['world']." is not authorised\n");
295 }
296
297 //############################################################################
298 //# Decode the Array Information that has been pass in. #
299 //############################################################################
300
301 // Decode the Position array into the $position array. 0->x, 1->y, 2->z
302 $position_string = substr($readings['position'], 1, -1); // Remove leading and trailing angle brackets
303 $pos = explode(",", $position_string);
304 $position = array_slice($pos, 0, 3);
305
306 // Decode the Rotation into the rotation array. 0->x, 1->y, 2->z, 3->s
307 $rotation_string = substr($readings['rotation'], 1, -1); // Remove leading and trailing angle breackets
308 $rot = explode(",", $rotation_string);
309 $rotation = array_slice($rot, 0, 4);
310
311 //###################################################################
312 //# Determine if this teleporter is already known #
313 //###################################################################
314
315 // Determine if this heartbeat is from an already known Teleporter
316 $sql_query = "select * from ls_os_teleport where teleport_key = :key";
317 try
318 {
319 $stmt = $pdo->prepare($sql_query);
320 $stmt->execute(['key' => $readings['key']]);
321 $exists = $stmt->fetch(PDO::FETCH_ASSOC);
322 }
323 catch (Exception $e)
324 {
325 echo "FAILURE=IDENTIFY:".$e->getMessage()."\n";
326 }
327
328 //###################################################################
329 //# If this entry is found, then this just an update #
330 //###################################################################
331 if ($exists)
332 {
333 // Get the Substitution Fields
334 $data =
335 [
336 $readings['name'], $readings['owner'], $readings['world'], $readings['region'],
337 $position[0], $position[1], $position[2],
338 $rotation[0], $rotation[1], $rotation[2], $rotation[3],
339 $readings['offset'], $readings['group'], $readings['offsetangle'],
340 $readings['locationinfo'], $readings['vernum'], $readings['localitygroup'],
341 $readings['key']
342 ];
343
344 // Create the command to run to make the update
345 $sql_query = "update ls_os_teleport set ";
346 $sql_query .= "teleport_name = ?, teleport_owner_key = ?, teleport_world = ?, teleport_region = ?, ";
347 $sql_query .= "teleport_region_x = ?, teleport_region_y = ?, teleport_region_z = ?, ";
348 $sql_query .= "teleport_rotation_x = ?, teleport_rotation_y = ?, teleport_rotation_z = ?, teleport_rotation_s = ?, ";
349 $sql_query .= "teleport_offset = ?, teleport_group_key = ?, teleport_front_offset_angle = ?, ";
350 $sql_query .= "teleport_location_info = ?, teleport_version_number = ?, teleport_locality_group = ?, ";
351 $sql_query .= "teleport_heartbeat = CURRENT_TIMESTAMP()";
352 $sql_query .= "where teleport_key = ?";
353
354 // Attempt to Update the Database Entry for this Teleporter
355 try
356 {
357 $stmt = $pdo->prepare($sql_query);
358 $stmt->execute($data);
359 }
360 catch (Exception $e)
361 {
362 echo "FAILURE=UPDATE:".$e->getMessage()."\n";
363 }
364 }
365
366 //###################################################################
367 //# If it wasn't Found, It is a new Teleporter #
368 //###################################################################
369 else
370 {
371 // Test to see if this new item has an name that already exists in the database.
372 // Duplicate name are not permitted to prevent tue users becoming confused. If it
373 // is a duplicate, send a warning that there is a name violation to the owner of
374 // this new teleporter.
375
376 $sql_query = "select * from ls_os_teleport where teleport_name = :name";
377 try
378 {
379 $stmt = $pdo->prepare($sql_query);
380 $stmt->execute(['name' => $readings['name']]);
381 $same_name = $stmt->fetch(PDO::FETCH_ASSOC);
382 }
383 catch (Exception $e)
384 {
385 echo "FAILURE=NAME_MATCH: ".$readings['name'].":Failed with".$e->getMessage()."\n";
386 }
387 if ($same_name)
388 {
389 echo "FAILURE=NAME_MATCH: Existing teleporter data - ";
390 echo $row['teleport_world']."/".$row['teleport_region']."/";
391 echo "<".$row['teleport_region_x'].",".$row['teleport_region_y'].",".$row['teleport_region_z'].">\n";
392 }
393 else
394 {
395 // Get the Substitution Fields
396 $data =
397 [
398 $readings['key'], $readings['name'], $readings['owner'], $readings['world'], $readings['region'],
399 $position[0], $position[1], $position[2],
400 $rotation[0], $rotation[1], $rotation[2], $rotation[3],
401 $readings['offset'], $readings['group'], $readings['offsetangle'],
402 $readings['locationinfo'], $readings['vernum'], $readings['localitygroup']
403 ];
404
405 // Create the command to run to make the insert
406 $sql_query = "insert into ls_os_teleport(";
407 $sql_query .= "teleport_key, teleport_name, teleport_owner_key, teleport_world, teleport_region, ";
408 $sql_query .= "teleport_region_x, teleport_region_y, teleport_region_z, ";
409 $sql_query .= "teleport_rotation_x, teleport_rotation_y, teleport_rotation_z, teleport_rotation_s, ";
410 $sql_query .= "teleport_offset, teleport_group_key, teleport_front_offset_angle,";
411 $sql_query .= "teleport_location_info, teleport_version_number, teleport_locality_group";
412 $sql_query .= ")VALUES(";
413 $sql_query .= "?, ?, ?, ?, ?, ";
414 $sql_query .= "?, ?, ?, ";
415 $sql_query .= "?, ?, ?, ?, ";
416 $sql_query .= "?, ?, ?, ";
417 $sql_query .= "?, ?, ?";
418 $sql_query .= ")";
419
420 // Attempt to Update the Database Entry for this Teleporter
421 try
422 {
423 $stmt = $pdo->prepare($sql_query);
424 $stmt->execute($data);
425 }
426 catch (Exception $e)
427 {
428 echo "FAILURE=INSERT:".$e->getMessage()."\n";
429 }
430 }
431 }
432
433 // Send the Message Preamble
434 echo "EXTRACT_LIST=START\n";
435
436 // Isolate the Individual Flags from the location information
437 $this_group_flag = $readings['locationinfo'] & $GROUP_FLAG;
438 $this_region_flag = $readings['locationinfo'] & $REGION_FLAG;
439 $this_world_flag = $readings['locationinfo'] & $WORLD_FLAG;
440 $this_metaverse_flag = $readings['locationinfo'] & $METAVERSE_FLAG;
441
442 $sql_query = "";
443
444 // Depending on the options selected in the LOCATION_TYPES in the configuration file, this query will
445 // make a selection destinations in the region holding the Teleporter. LOCAL will select all destinations
446 // that have a LOCALITY_GROUP that matches the LOCALITY_GROUP value.
447 $sql_query .= "select * from ls_os_teleport";
448 $sql_query .= " where teleport_key != :key";
449 $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)";
450 $sql_query .= " and teleport_location_info & :anon_flag = 0";
451 $sql_query .= " and teleport_region = :region";
452 $sql_query .= " and teleport_world = :world";
453 $sql_query .= " and teleport_version_number != 0";
454
455 $sql_query .= " UNION ";
456
457 // Check if this s a World or Meteverse Location
458 $sql_query .= "select * from ls_os_teleport ";
459 $sql_query .= " where teleport_key != :key";
460 $sql_query .= " and ((teleport_location_info & :world_flag = :this_world_flag and teleport_world = :world)";
461 $sql_query .= " and teleport_location_info & :anon_flag = 0";
462 $sql_query .= " or (teleport_location_info & :metaverse_flag = :this_metaverse_flag and teleport_world != :world))";
463 $sql_query .= " and teleport_version_number != 0";
464
465 // Sort the Responses into Alphbetical Order
466 $sql_query .= " order by teleport_name";
467
468 $parameters = [
469 'key' => $readings['key'],
470 'group_flag' => $GROUP_FLAG,
471 'region_flag' => $REGION_FLAG,
472 'world_flag' => $WORLD_FLAG,
473 'metaverse_flag' => $METAVERSE_FLAG,
474 'anon_flag' => $ANONYMOUS_FLAG,
475 'this_group_flag' => $this_group_flag,
476 'this_region_flag' => $this_region_flag,
477 'this_world_flag' => $this_world_flag,
478 'this_metaverse_flag' => $this_metaverse_flag,
479 'group' => $readings['localitygroup'],
480 'region'=> $readings['region'],
481 'world' => $readings['world']
482 ];
483
484 $this->rdSelectDestinations($sql_query, $parameters, $pdo, $readings['world'], $readings['region']);
485
486 // Send the Message Postamble
487 sleep(1);
488 echo "EXTRACT_LIST=END\n";
489 }
490
491 // If the Command is a Scan, Process the Destination Entries in the Support Database
492 if ($readings['command'] == "scan")
493 {
494
495 //#############################################################################
496 //## Scan the Contents of the Destinations for recent Heartbeats ##
497 //#############################################################################
498 // Remove the Teleporter if they havw exceeded their lifetime without sending
499 // a heartbeat message. Destinations that did not come from a Teleporter, that
500 // manually entered are not affected by this process, but are identified as
501 //being past End Of Life (EOL).
502
503 $world = $readings['world'];
504
505 $SqlQuery = "select * from ls_os_teleport";
506 $SqlQuery .= "where DATE_ADD(teleport_heartbeat, INTERVAL :lifetime HOUR) < CURRENT_TIMESTAMP()";
507 $SqlQuery .= " and teleport_version_number != 0 ";
508 if ($world != '###') $SqlQuery .= " and teleport_world = :world";
509 $SqlQuery .= " order by teleport_name;";
510
511 $Parameters = ['lifetime' => $readings['lifetime'] ];
512 if ($world != '###') $Parameters['world'] = $world;
513
514 try
515 {
516 $stmt = $pdo->prepare($SqlQuery);
517 $stmt->execute($Parameters);
518 $results = $stmt->fetchAll(PDO::FETCH_DEFAULT);
519 }
520 catch (Exception $e)
521 {
522 echo "FAILURE=SCAN:".$e->getMessage()."\n";
523 }
524
525 //#########################################################################################
526 //# Process Each Line #
527 //#########################################################################################
528
529 echo "SCAN_LIST=START\n";
530 echo "//=========================== Date: ".date("Y-m-d H:i:s")."==================\n";
531
532 foreach ($results as $row)
533 {
534 $action_string = "SCANNED";
535 $teleport_name = $row['teleport_name'];
536 $teleport_version = $row['teleport_version_number'];
537
538 // If OnlyScn is FALSE, delete the teleporter from the teleporter table
539 if ($readings['onlyscan'] == 0)
540 {
541 $sql_query1 = "delete from ls_os_teleport where teleport_key = :key";
542 $parameters1 = ['key' => $row['teleport_key'] ];
543 $stmt1 = $pdo->prepare($sql_query1);
544 $stmt1->execute($parameters1);
545 $results1 = $stmt1->fetchAll(PDO::FETCH_DEFAULT);
546 $action_string = "DELETED";
547 }
548 echo $row['teleport_name']."|".$action_string."|";
549 echo "hop://".$row['teleport_world']."/".$row['teleport_region']."/".$row['teleport_region_x']."/".$row['teleport_region_y']."/".$row['teleport_region_z']."\n";
550 }
551 echo "SCAN_LIST=END\n";
552 }
553 }
554}
555
556//=================================================================================
557// Initialise the Parameters from the URL
558//=================================================================================
559
560// Get the Parameters passed to the Program and Decode them
561$parameters = json_encode($_GET);
562$readings = json_decode( $parameters, true );
563
565$my_teleport->rdProcessTeleport();
566
567?>
568
All of the Routines to Control the Teleporter Database.
Definition teleport.php:31
rdSelectDestinations($SqlQuery, $Parameters, $Pdo, $ThisWorld, $ThisRegion)
Print out the selected teleporters for the Destination Notecard.
Definition teleport.php:44
rdConfirmUser($UseSimDb, $PDO, $PDO1)
Fucntion to confirm that the object's owner is authorise to run script.
Definition teleport.php:113
rdProcessTeleport()
The public function that does all the work.
Definition teleport.php:213
rdOpenDatabase($Database, $Host, $Username, $Password)
Open the Support Database for Use.
Definition teleport.php:170
$readings
Definition teleport.php:562
$my_teleport
Definition teleport.php:564
$parameters
Definition teleport.php:561