Database Teleporter BRIGADOON-0009
An Open Simulator Teleporter using a central database.
Loading...
Searching...
No Matches
rdTeleport Class Reference

All of the Routines to Control the Teleporter Database. More...

Public Member Functions

 rdSelectDestinations ($SqlQuery, $Parameters, $Pdo, $ThisWorld, $ThisRegion)
 Print out the selected teleporters for the Destination Notecard.
 rdConfirmUser ($UseSimDb, $PDO, $PDO1)
 Fucntion to confirm that the object's owner is authorise to run script.
 rdOpenDatabase ($Database, $Host, $Username, $Password)
 Open the Support Database for Use.
 rdProcessTeleport ()
 The public function that does all the work.

Detailed Description

All of the Routines to Control the Teleporter Database.

Definition at line 30 of file teleport.php.

Member Function Documentation

◆ rdConfirmUser()

rdTeleport::rdConfirmUser ( $UseSimDb,
$PDO,
$PDO1 )

Fucntion to confirm that the object's owner is authorise to run script.

Parameters
$UseSimDbFlag to indicate if the OpenSim database UserAccounts is to be used
$PDOThe database instance to access the local ls_os_teleport_allowed table
$PDO1The database instance to access the OpenSim UserAccounts table

This routine checks if it is allowed to access the OpenSim database UserAccounts file to determine if the owner of this object is known. If it is, and the user is found, the routine exits.

If the UserAccounts file cannot be used, or the user is not found in that file, the local ls_os_teleport_allowed table is queried. If the owner cannot be found in that table, then the script will abort.

If the user ias found in that table, the routine will set the world where the user exists and whether that user is currently allowed to change the contents of the teleporter table.

Definition at line 113 of file teleport.php.

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 }
$readings
Definition teleport.php:562

References $readings.

Referenced by rdProcessTeleport().

Here is the caller graph for this function:

◆ rdOpenDatabase()

rdTeleport::rdOpenDatabase ( $Database,
$Host,
$Username,
$Password )

Open the Support Database for Use.

Parameters
$DatabaseThe Name of the Database to Open
$HostThe name of the computer use to conenct to the Database
$UsernameThe username to access the Database
$PasswordThe password to access the database.

If this routine fails, it will case the program to abort and the heartbeat will neither identify itself as being on-line and it will not update the list of destinations.

Definition at line 170 of file teleport.php.

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 }

Referenced by rdProcessTeleport().

Here is the caller graph for this function:

◆ rdProcessTeleport()

rdTeleport::rdProcessTeleport ( )

The public function that does all the work.

The function has three main activities:

(1) Insert new teleporters into the database;
(2) Update existing teleporter entries in the database, including the heartbeat time.
(3) Scan teleporter database for potentially dead teleporters and remove if required.

Definition at line 213 of file teleport.php.

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 }
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
rdOpenDatabase($Database, $Host, $Username, $Password)
Open the Support Database for Use.
Definition teleport.php:170
$parameters
Definition teleport.php:561

References $parameters, $readings, rdConfirmUser(), rdOpenDatabase(), and rdSelectDestinations().

Here is the call graph for this function:

◆ rdSelectDestinations()

rdTeleport::rdSelectDestinations ( $SqlQuery,
$Parameters,
$Pdo,
$ThisWorld,
$ThisRegion )

Print out the selected teleporters for the Destination Notecard.

Parameters
$SqlQueryThe SQL Query to select the Teleporters
$ParametersThe Parameters to inser into the SQL Query
$PdoThe Database instance to use to access the Database
$ThisWorldThe address of the world the Script is in
$ThisRegionThe name of the region this SCript is in

This routine extracts the selected entries for the ls_os_teleport table, formats the data and send it out for return to teh calling OPen Simulator script.

Definition at line 44 of file teleport.php.

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 }

Referenced by rdProcessTeleport().

Here is the caller graph for this function:

The documentation for this class was generated from the following file: