1
0
Fork 0

add files

master
Christopher Latza 2020-06-03 17:31:18 +02:00
parent b9bdbd9825
commit 9401416c63
1958 changed files with 201441 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config.php

View File

@ -1,2 +1,2 @@
# Manager
# OpenSim-Gridverwaltung

1
api/.htaccess Normal file
View File

@ -0,0 +1 @@
Deny from all

5
api/getAccessList.php Normal file
View File

@ -0,0 +1,5 @@
1148b04d-7a93-19e9-b3c9-ea1cdeec38f7
1148b04d-7a93-29e9-b3c9-ea1cdeec38f7
1148b04d-7a93-39e9-b3c9-ea1cdeec38f7
1148b04d-7a93-49e9-b3c9-ea1cdeec38f7
1148b04d-7a93-59e9-b3c9-ea1cdeec38f7

34
api/onlineDisplay.php Normal file
View File

@ -0,0 +1,34 @@
<html>
<head>
<meta http-equiv="refresh" content="15">
</head>
<body style="background-image: url('./style/images/fabric-pattern.png')">
<?php
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM Presence WHERE RegionID != '00000000-0000-0000-0000-000000000000' ORDER BY RegionID ASC");
$statement->execute();
if($statement->rowCount() == 0)
{
echo "<h1>Es ist niemand online!</h1>";
}else{
echo '<table style="width:350px;margin-left:auto;margin-right:auto;margin-top:25px"><tr><th align="left" style="background-color: #FF8000;">Name</th><th align="left" style="background-color: #FF8000;">Region</th></tr>';
$entryColor = TRUE;
while($row = $statement->fetch())
{
if($entryColor == TRUE)
$entry = '<tr style="background-color: #F2F2F2;"><td>'.trim($RUNTIME['OPENSIM']->getUserName($row['UserID'])).'</td><td>'.$RUNTIME['OPENSIM']->getRegionName($row['RegionID']).'</td></tr>';
if($entryColor == FALSE)
$entry = '<tr style="background-color: #E6E6E6;"><td>'.trim($RUNTIME['OPENSIM']->getUserName($row['UserID'])).'</td><td>'.$RUNTIME['OPENSIM']->getRegionName($row['RegionID']).'</td></tr>';
echo $entry;
$entryColor = !$entryColor;
}
echo '</table>';
}
?>
</body>
</html>

34
api/viewerWelcomeSite.php Normal file
View File

@ -0,0 +1,34 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Spalsh");
$HTML->importHTML("style/viewerWelcomeSite/default.html");
$IMAGES = array();
if ($handle = opendir('./data/viewerWelcomeImages'))
{
while (false !== ($entry = readdir($handle)))
{
if ($entry != "." && $entry != "..")
{
$IMAGES = array_merge($IMAGES, array("./data/viewerWelcomeImages/".$entry));
}
}
closedir($handle);
}
shuffle($IMAGES);
$HTML->importSeitenInhalt("pages/HTML/viewerWelcomeImages.html");
$HTML->ReplaceSeitenInhalt("%%JSONIMAGEARRAY%%", json_encode($IMAGES));
$HTML->ReplaceSeitenInhalt("%%GRIDNAME%%", $RUNTIME['GRID']['NAME']);
$HTML->ReplaceSeitenInhalt("%%SHOWNEWS%%", $RUNTIME['GRID']['MAIN_NEWS']);
$HTML->ReplaceSeitenInhalt("%%SHOWSTATS%%", "Registrierte User: ".$RUNTIME['OPENSIM']->getUserCount()."<br>Regionen: ".$RUNTIME['OPENSIM']->getRegionCount()."<br>Aktuell Online: ".$RUNTIME['OPENSIM']->getOnlineCount());
$HTML->build();
echo $HTML->ausgabe();
?>

View File

@ -0,0 +1,252 @@
<?php
/**
* PHP Class for handling Google Authenticator 2-factor authentication.
*
* @author Michael Kliewe
* @copyright 2012 Michael Kliewe
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*
* @link http://www.phpgangsta.de/
*/
class PHPGangsta_GoogleAuthenticator
{
protected $_codeLength = 6;
/**
* Create new secret.
* 16 characters, randomly chosen from the allowed base32 characters.
*
* @param int $secretLength
*
* @return string
*/
public function createSecret($secretLength = 16)
{
$validChars = $this->_getBase32LookupTable();
// Valid secret lengths are 80 to 640 bits
if ($secretLength < 16 || $secretLength > 128) {
throw new Exception('Bad secret length');
}
$secret = '';
$rnd = false;
if (function_exists('random_bytes')) {
$rnd = random_bytes($secretLength);
} elseif (function_exists('mcrypt_create_iv')) {
$rnd = mcrypt_create_iv($secretLength, MCRYPT_DEV_URANDOM);
} elseif (function_exists('openssl_random_pseudo_bytes')) {
$rnd = openssl_random_pseudo_bytes($secretLength, $cryptoStrong);
if (!$cryptoStrong) {
$rnd = false;
}
}
if ($rnd !== false) {
for ($i = 0; $i < $secretLength; ++$i) {
$secret .= $validChars[ord($rnd[$i]) & 31];
}
} else {
throw new Exception('No source of secure random');
}
return $secret;
}
/**
* Calculate the code, with given secret and point in time.
*
* @param string $secret
* @param int|null $timeSlice
*
* @return string
*/
public function getCode($secret, $timeSlice = null)
{
if ($timeSlice === null) {
$timeSlice = floor(time() / 30);
}
$secretkey = $this->_base32Decode($secret);
// Pack time into binary string
$time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice);
// Hash it with users secret key
$hm = hash_hmac('SHA1', $time, $secretkey, true);
// Use last nipple of result as index/offset
$offset = ord(substr($hm, -1)) & 0x0F;
// grab 4 bytes of the result
$hashpart = substr($hm, $offset, 4);
// Unpak binary value
$value = unpack('N', $hashpart);
$value = $value[1];
// Only 32 bits
$value = $value & 0x7FFFFFFF;
$modulo = pow(10, $this->_codeLength);
return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT);
}
/**
* Get QR-Code URL for image, from google charts.
*
* @param string $name
* @param string $secret
* @param string $title
* @param array $params
*
* @return string
*/
public function getQRCodeGoogleUrl($name, $secret, $title = null, $params = array())
{
$width = !empty($params['width']) && (int) $params['width'] > 0 ? (int) $params['width'] : 200;
$height = !empty($params['height']) && (int) $params['height'] > 0 ? (int) $params['height'] : 200;
$level = !empty($params['level']) && array_search($params['level'], array('L', 'M', 'Q', 'H')) !== false ? $params['level'] : 'M';
$urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.'');
if (isset($title)) {
$urlencoded .= urlencode('&issuer='.urlencode($title));
}
return "https://api.qrserver.com/v1/create-qr-code/?data=$urlencoded&size=${width}x${height}&ecc=$level";
}
/**
* Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now.
*
* @param string $secret
* @param string $code
* @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
* @param int|null $currentTimeSlice time slice if we want use other that time()
*
* @return bool
*/
public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice = null)
{
if ($currentTimeSlice === null) {
$currentTimeSlice = floor(time() / 30);
}
if (strlen($code) != 6) {
return false;
}
for ($i = -$discrepancy; $i <= $discrepancy; ++$i) {
$calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
if ($this->timingSafeEquals($calculatedCode, $code)) {
return true;
}
}
return false;
}
/**
* Set the code length, should be >=6.
*
* @param int $length
*
* @return PHPGangsta_GoogleAuthenticator
*/
public function setCodeLength($length)
{
$this->_codeLength = $length;
return $this;
}
/**
* Helper class to decode base32.
*
* @param $secret
*
* @return bool|string
*/
protected function _base32Decode($secret)
{
if (empty($secret)) {
return '';
}
$base32chars = $this->_getBase32LookupTable();
$base32charsFlipped = array_flip($base32chars);
$paddingCharCount = substr_count($secret, $base32chars[32]);
$allowedValues = array(6, 4, 3, 1, 0);
if (!in_array($paddingCharCount, $allowedValues)) {
return false;
}
for ($i = 0; $i < 4; ++$i) {
if ($paddingCharCount == $allowedValues[$i] &&
substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) {
return false;
}
}
$secret = str_replace('=', '', $secret);
$secret = str_split($secret);
$binaryString = '';
for ($i = 0; $i < count($secret); $i = $i + 8) {
$x = '';
if (!in_array($secret[$i], $base32chars)) {
return false;
}
for ($j = 0; $j < 8; ++$j) {
$x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
}
$eightBits = str_split($x, 8);
for ($z = 0; $z < count($eightBits); ++$z) {
$binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : '';
}
}
return $binaryString;
}
/**
* Get array with all 32 characters for decoding from/encoding to base32.
*
* @return array
*/
protected function _getBase32LookupTable()
{
return array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
'=', // padding char
);
}
/**
* A timing safe equals comparison
* more info here: http://blog.ircmaxell.com/2014/11/its-all-about-time.html.
*
* @param string $safeString The internal (safe) value to be checked
* @param string $userString The user submitted (unsafe) value
*
* @return bool True if the two strings are identical
*/
private function timingSafeEquals($safeString, $userString)
{
if (function_exists('hash_equals')) {
return hash_equals($safeString, $userString);
}
$safeLen = strlen($safeString);
$userLen = strlen($userString);
if ($userLen != $safeLen) {
return false;
}
$result = 0;
for ($i = 0; $i < $userLen; ++$i) {
$result |= (ord($safeString[$i]) ^ ord($userString[$i]));
}
// They are only identical strings if $result is exactly 0...
return $result === 0;
}
}

242
classen/HTML.php Normal file
View File

@ -0,0 +1,242 @@
<?php
class HTML
{
//Hier wird der HTML Code zum Ausgeben vorbereitet.
//Dieser kann aus einer fertigen HTML Seite ausgelesen werden, oder aber auch st<73>ck f<>r St<53>ck
//Zusammen gebaut werden.
//Die Einzelnen Daten k<>nnen nicht direkt von Au<41>en ver<65>ndert werden, sondern m<>ssen durch die Bereitgestellten Optionen gesetzt werden.
private $HTMLTitle = " "; //Wird in den <header> als <title> Geschrieben.
private $StatusMeldung = " "; //Falls Vorhenden eine Statusmeldung vom Script im HTML Text.
private $DasMenu = " "; //Beinhaltet das Fertige Men<65>
private $DerInhalt = " "; //Beinhaltet den Fertigen Inhalt
private $HTMLDatei = " "; //Der inhalt der eingelesen wurde.
private $HTMLHeader = " "; //Der HTML HEADER der eingelesen wurde.
private $FertigesHTML = " "; //Das Fertige HTML bereit zum Ausgeben.
private $isBuild = false; //Hier wird festgehalten ob $FertigesHTML aktuell ist oder nicht.
//Der <title> wird Generiert.(%%EchoTitle%%)
//Dieser wird im HTML Code sp<73>ter als %%HTMLTitle%% aufgerufen.
public function setHTMLTitle($neuerTitle){
//Der Bisherige Title wird komplett <20>berschrieben und gleichzeitig ein neuer Gesetzt.
$this->HTMLTitle = $neuerTitle;
$this->isBuild = false;
}
public function addHTMLTitle($Hinzufugen){
//Zu dem Bisherigen Titel wird noch etwas am ende hinzugef<65>gt.
$this->HTMLTitle = $this->$HTMLTitle.$Hinzufugen;
$this->isBuild = false;
}
public function RemoveHTMLTitle(){
//Der Titel wird Komplett gel<65>scht.
$this->HTMLTitle = " ";
$this->isBuild = false;
}
//Der HTML HEADER wird Generiert.(%%echoHeader%%)
//Dieser wird im HTML Code sp<73>ter als %%echoHeader%% aufgerufen.
public function setHTMLHeader($neuerHeader){
//Der Bisherige Header wird komplett <20>berschrieben und gleichzeitig ein neuer Gesetzt.
$this->HTMLHeader = $neuerHeader;
$this->isBuild = false;
}
public function addHTMLHeader($Hinzufugen){
//Zu dem Bisherigen Header wird noch etwas am ende hinzugef<65>gt.
$this->HTMLHeader = $this->HTMLHeader.$Hinzufugen;
$this->isBuild = false;
}
public function RemoveHTMLHeader(){
//Der Header wird Komplett gel<65>scht.
$this->HTMLHeader = " ";
$this->isBuild = false;
}
public function importHTMLHeader($file){
//Der HTML Header wird aus einer Datei eingelesen und der bisherige gel<65>scht.
$this->HTMLHeader = file_get_contents($file);
$this->isBuild = false;
}
//Der StatusText wird ge<67>ndert.(%%StatusMeldung%%)
//Dieser wird im HTML Code sp<73>ter als %%StatusMeldung%% aufgerufen.
public function setStatusMeldung($neueMeldung){
//Die bisherige Status meldung wird komplett <20>berschrieben und gleichzeitig ein neuer Gesetzt.
$this->StatusMeldung = $neueMeldung;
$this->isBuild = false;
}
public function RemoveStatusMeldung(){
//Die Meldung wird Komplett gel<65>scht.
$this->StatusMeldung = " ";
$this->isBuild = false;
}
//Ab hier wird das Men<65> Zusammengebaut. (%%EchoMenu%%)
public function importTextMenu($neuesMenu){
//Das Komplette Men<65> wird direkt importiert und das alte <20>berschreiben.
$this->DasMenu = $neuesMenu;
$this->isBuild = false;
}
public function importHTMLMenu($file){
//Das Komplette Men<65> wird aus einer Datei ausgelesen und das alte <20>berschrieben.
$this->DasMenu = file_get_contents($file);
$this->isBuild = false;
}
public function addToMenu($html){
//Es wird noch etwas ans Men<65> angehengt.
$this->DasMenu = $this->$DasMenu.$html;
$this->isBuild = false;
}
//Der Seiten HTML Quelcode wird eingelesen.
public function importHTML($file){
//Der HTML Quelltext wird aus einer Datei eingelesen.
$this->HTMLDatei = file_get_contents($file);
$this->isBuild = false;
}
public function setHTML($htmlCode){
//Der HTML Quelltext wird direkt gesetzt.
$this->HTMLDatei = $htmlCode;
$this->isBuild = false;
}
public function addNachHTML($htmlCode){
//Der HTML Quelltext wird direkt gesetzt.
$this->HTMLDatei = $this->HTMLDatei.$htmlCode;
$this->isBuild = false;
}
public function addVorHTML($htmlCode){
//Der HTML Quelltext wird direkt gesetzt.
$this->HTMLDatei = $htmlCode.$this->HTMLDatei;
$this->isBuild = false;
}
public function DeleteHTML(){
//Der HTML Quelltext wird gel<65>scht.
$this->HTMLDatei = " ";
$this->isBuild = false;
}
//Der inhalt der Seite wird zusammen gesetzt (nicht der quelltext) (%%EchoInhalt%%)
public function importSeitenInhalt($file){
//L<>d einen fertigen Text aus einer datei.
$this->DerInhalt = file_get_contents($file);
$this->isBuild = false;
}
public function setSeitenInhalt($html){
//Setz den Seiteninhalt und L<>scht den alten Komplett.
$this->DerInhalt = $html;
$this->isBuild = false;
}
public function importAndAddSeitenInhalt($file){
//L<>d einen fertigen Text aus einer datei.
$this->DerInhalt = $this->DerInhalt.file_get_contents($file);
$this->isBuild = false;
}
public function addToSeitenInhalt($html){
//Es wird noch weitere Text an den Seiteninhalt angeh<65>ngt.
$this->DerInhalt = $this->DerInhalt.$html;
$this->isBuild = false;
}
public function GetSeitenInhalt(){
//Der Seiteninhalt wird zur<75>ckgegeben.
return $this->DerInhalt;
}
public function DeleteSeitenInhalt(){
//L<>scht den Seiten inhalt.
$this->DerInhalt = " ";
$this->isBuild = false;
}
public function ReplaceSeitenInhalt($tag, $text){
//Ersezt Seiten Inhalt
$this->DerInhalt = str_replace($tag, $text, $this->DerInhalt);
}
public function ReplaceLayoutInhalt($tag, $text){
//Ersezt Layout Inhalt
$this->HTMLDatei = str_replace($tag, $text, $this->HTMLDatei);
}
public function CompressHTML(){
if($this->isBuild){
$this->FertigesHTML = str_replace(" ", "", $this->FertigesHTML);
$this->FertigesHTML = str_replace(" ", "", $this->FertigesHTML);
}else{
die("Es kann nur Fertiger HTML Code kompremiert werden.");
return false;
}
}
//Hier wird der Fertige HTML Code generiert.
//Und alle 3 Teile, Men<65> Titel und inhalt zusammengef<65>gt.
public function build(){
//Der HTML Code wird zusammen gesetzt.
$this->FertigesHTML = null; //Der Speicher wird gellert, falls schon einmal Quelltext generiert wurde.
$this->FertigesHTML = $this->HTMLDatei; //Und der Unverarbeitete HTML Quelltext eingelesen.
//Das Men<65> wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%EchoMenu%%", $this->DasMenu, $this->FertigesHTML);
//Der inhalt wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%EchoInhalt%%", $this->DerInhalt, $this->FertigesHTML);
//Die Status Meldung wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%StatusMeldung%%", $this->StatusMeldung, $this->FertigesHTML);
//Der Titel wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%EchoTitle%%", $this->HTMLTitle, $this->FertigesHTML);
//Der HTML Header wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%echoHeader%%", $this->HTMLHeader, $this->FertigesHTML);
//Der Titel wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%datum%%", date("Y-m-dTH:i+2"), $this->FertigesHTML);
//Der Counter wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%GET_SITE%%", @$_GET['seite'], $this->FertigesHTML);
//Die IP Adresse wird in den HTML Quellcode eingef<65>gt.
$this->FertigesHTML = str_replace("%%GET_IP%%", @$_SERVER["REMOTE_ADDR"], $this->FertigesHTML);
$this->isBuild = true;
}
//Hier wird der Fertige HTML ausgegeben
public function ausgabe(){
if($this->isBuild){
return $this->FertigesHTML;
}else{
die("Bitte erst den HTML Code zusammensetzen.");
return false;
}
}
}
?>

View File

@ -0,0 +1,37 @@
<?php
/**
* PHPMailer Exception class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2017 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer exception handler.
*
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
*/
class Exception extends \Exception
{
/**
* Prettify error message output.
*
* @return string
*/
public function errorMessage()
{
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n";
}
}

136
classen/MAIL/OAuth.php Normal file
View File

@ -0,0 +1,136 @@
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2015 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
use League\OAuth2\Client\Grant\RefreshToken;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;
/**
* OAuth - OAuth2 authentication wrapper class.
* Uses the oauth2-client package from the League of Extraordinary Packages.
*
* @see http://oauth2-client.thephpleague.com
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
*/
class OAuth
{
/**
* An instance of the League OAuth Client Provider.
*
* @var AbstractProvider
*/
protected $provider;
/**
* The current OAuth access token.
*
* @var AccessToken
*/
protected $oauthToken;
/**
* The user's email address, usually used as the login ID
* and also the from address when sending email.
*
* @var string
*/
protected $oauthUserEmail = '';
/**
* The client secret, generated in the app definition of the service you're connecting to.
*
* @var string
*/
protected $oauthClientSecret = '';
/**
* The client ID, generated in the app definition of the service you're connecting to.
*
* @var string
*/
protected $oauthClientId = '';
/**
* The refresh token, used to obtain new AccessTokens.
*
* @var string
*/
protected $oauthRefreshToken = '';
/**
* OAuth constructor.
*
* @param array $options Associative array containing
* `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
*/
public function __construct($options)
{
$this->provider = $options['provider'];
$this->oauthUserEmail = $options['userName'];
$this->oauthClientSecret = $options['clientSecret'];
$this->oauthClientId = $options['clientId'];
$this->oauthRefreshToken = $options['refreshToken'];
}
/**
* Get a new RefreshToken.
*
* @return RefreshToken
*/
protected function getGrant()
{
return new RefreshToken();
}
/**
* Get a new AccessToken.
*
* @return AccessToken
*/
protected function getToken()
{
return $this->provider->getAccessToken(
$this->getGrant(),
['refresh_token' => $this->oauthRefreshToken]
);
}
/**
* Generate a base64-encoded OAuth token.
*
* @return string
*/
public function getOauth64()
{
// Get a new token if it's not available or has expired
if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
$this->oauthToken = $this->getToken();
}
return base64_encode(
'user=' .
$this->oauthUserEmail .
"\001auth=Bearer " .
$this->oauthToken .
"\001\001"
);
}
}

4818
classen/MAIL/PHPMailer.php Normal file

File diff suppressed because it is too large Load Diff

419
classen/MAIL/POP3.php Normal file
View File

@ -0,0 +1,419 @@
<?php
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2019 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
* 1) This class does not support APOP authentication.
* 2) Opening and closing lots of POP3 connections can be quite slow. If you need
* to send a batch of emails then just perform the authentication once at the start,
* and then loop through your mail sending script. Providing this process doesn't
* take longer than the verification period lasts on your POP3 server, you should be fine.
* 3) This is really ancient technology; you should only need to use it to talk to very old systems.
* 4) This POP3 class is deliberately lightweight and incomplete, implementing just
* enough to do authentication.
* If you want a more complete class there are other POP3 classes for PHP available.
*
* @author Richard Davey (original author) <rich@corephp.co.uk>
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
*/
class POP3
{
/**
* The POP3 PHPMailer Version number.
*
* @var string
*/
const VERSION = '6.1.5';
/**
* Default POP3 port number.
*
* @var int
*/
const DEFAULT_PORT = 110;
/**
* Default timeout in seconds.
*
* @var int
*/
const DEFAULT_TIMEOUT = 30;
/**
* Debug display level.
* Options: 0 = no, 1+ = yes.
*
* @var int
*/
public $do_debug = 0;
/**
* POP3 mail server hostname.
*
* @var string
*/
public $host;
/**
* POP3 port number.
*
* @var int
*/
public $port;
/**
* POP3 Timeout Value in seconds.
*
* @var int
*/
public $tval;
/**
* POP3 username.
*
* @var string
*/
public $username;
/**
* POP3 password.
*
* @var string
*/
public $password;
/**
* Resource handle for the POP3 connection socket.
*
* @var resource
*/
protected $pop_conn;
/**
* Are we connected?
*
* @var bool
*/
protected $connected = false;
/**
* Error container.
*
* @var array
*/
protected $errors = [];
/**
* Line break constant.
*/
const LE = "\r\n";
/**
* Simple static wrapper for all-in-one POP before SMTP.
*
* @param string $host The hostname to connect to
* @param int|bool $port The port number to connect to
* @param int|bool $timeout The timeout value
* @param string $username
* @param string $password
* @param int $debug_level
*
* @return bool
*/
public static function popBeforeSmtp(
$host,
$port = false,
$timeout = false,
$username = '',
$password = '',
$debug_level = 0
) {
$pop = new self();
return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
}
/**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
*
* @param string $host The hostname to connect to
* @param int|bool $port The port number to connect to
* @param int|bool $timeout The timeout value
* @param string $username
* @param string $password
* @param int $debug_level
*
* @return bool
*/
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
// If no port value provided, use default
if (false === $port) {
$this->port = static::DEFAULT_PORT;
} else {
$this->port = (int) $port;
}
// If no timeout value provided, use default
if (false === $timeout) {
$this->tval = static::DEFAULT_TIMEOUT;
} else {
$this->tval = (int) $timeout;
}
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
// Reset the error log
$this->errors = [];
// connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
if ($login_result) {
$this->disconnect();
return true;
}
}
// We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
/**
* Connect to a POP3 server.
*
* @param string $host
* @param int|bool $port
* @param int $tval
*
* @return bool
*/
public function connect($host, $port = false, $tval = 30)
{
// Are we already connected?
if ($this->connected) {
return true;
}
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
//Rather than suppress it with @fsockopen, capture it cleanly instead
set_error_handler([$this, 'catchWarning']);
if (false === $port) {
$port = static::DEFAULT_PORT;
}
// connect to the POP3 server
$errno = 0;
$errstr = '';
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #
$errno, // Error Number
$errstr, // Error Message
$tval
); // Timeout (seconds)
// Restore the error handler
restore_error_handler();
// Did we connect?
if (false === $this->pop_conn) {
// It would appear not...
$this->setError(
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
);
return false;
}
// Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
// Get the POP3 server response
$pop3_response = $this->getResponse();
// Check for the +OK
if ($this->checkResponse($pop3_response)) {
// The connection is established and the POP3 server is talking
$this->connected = true;
return true;
}
return false;
}
/**
* Log in to the POP3 server.
* Does not support APOP (RFC 2828, 4949).
*
* @param string $username
* @param string $password
*
* @return bool
*/
public function login($username = '', $password = '')
{
if (!$this->connected) {
$this->setError('Not connected to POP3 server');
}
if (empty($username)) {
$username = $this->username;
}
if (empty($password)) {
$password = $this->password;
}
// Send the Username
$this->sendString("USER $username" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
// Send the Password
$this->sendString("PASS $password" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
}
}
return false;
}
/**
* Disconnect from the POP3 server.
*/
public function disconnect()
{
$this->sendString('QUIT');
//The QUIT command may cause the daemon to exit, which will kill our connection
//So ignore errors here
try {
@fclose($this->pop_conn);
} catch (Exception $e) {
//Do nothing
}
}
/**
* Get a response from the POP3 server.
*
* @param int $size The maximum number of bytes to retrieve
*
* @return string
*/
protected function getResponse($size = 128)
{
$response = fgets($this->pop_conn, $size);
if ($this->do_debug >= 1) {
echo 'Server -> Client: ', $response;
}
return $response;
}
/**
* Send raw data to the POP3 server.
*
* @param string $string
*
* @return int
*/
protected function sendString($string)
{
if ($this->pop_conn) {
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
echo 'Client -> Server: ', $string;
}
return fwrite($this->pop_conn, $string, strlen($string));
}
return 0;
}
/**
* Checks the POP3 server response.
* Looks for for +OK or -ERR.
*
* @param string $string
*
* @return bool
*/
protected function checkResponse($string)
{
if (strpos($string, '+OK') !== 0) {
$this->setError("Server reported an error: $string");
return false;
}
return true;
}
/**
* Add an error to the internal error store.
* Also display debug output if it's enabled.
*
* @param string $error
*/
protected function setError($error)
{
$this->errors[] = $error;
if ($this->do_debug >= 1) {
echo '<pre>';
foreach ($this->errors as $e) {
print_r($e);
}
echo '</pre>';
}
}
/**
* Get an array of error messages, if any.
*
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* POP3 connection error handler.
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
*/
protected function catchWarning($errno, $errstr, $errfile, $errline)
{
$this->setError(
'Connecting to the POP3 server raised a PHP warning:' .
"errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
);
}
}

1369
classen/MAIL/SMTP.php Normal file

File diff suppressed because it is too large Load Diff

156
classen/OpenSim.php Normal file
View File

@ -0,0 +1,156 @@
<?php
class OpenSim
{
public function isLoginValid($name, $password)
{
global $RUNTIME;
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts WHERE FirstName = ? AND LastName = ? LIMIT 1");
$statementUser->execute(explode(" ", trim($name)));
while($rowUser = $statementUser->fetch())
{
$statementAuth = $RUNTIME['PDO']->prepare("SELECT * FROM auth WHERE UUID = ? LIMIT 1");
$statementAuth->execute(array($rowUser['PrincipalID']));
while($rowAuth = $statementAuth->fetch())
{
if(md5(md5($password).":".$rowAuth['passwordSalt']) == $rowAuth['passwordHash'])
{
return true;
}
}
}
return false;
}
public function getUserName($userID)
{
global $RUNTIME;
if(isset($RUNTIME['CACHE']['USERNAME'][$userID]))
return $RUNTIME['CACHE']['USERNAME'][$userID];
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts WHERE PrincipalID = ?");
$statementUser->execute(array($userID));
while($rowUser = $statementUser->fetch())
{
$RUNTIME['CACHE']['USERNAME'][$userID] = $rowUser['FirstName']." ".$rowUser['LastName'];
return $rowUser['FirstName']." ".$rowUser['LastName'];
}
return "Unknown User";
}
public function getUserUUID($UserName)
{
global $RUNTIME;
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts");
$statementUser->execute();
while($rowUser = $statementUser->fetch())
{
$SQLUserName = $rowUser['FirstName']." ".$rowUser['LastName'];
if($SQLUserName == $UserName)
{
return $rowUser['PrincipalID'];
}
}
return null;
}
public function getRegionName($regionID)
{
global $RUNTIME;
$statementRegion = $RUNTIME['PDO']->prepare("SELECT * FROM regions WHERE uuid = ?");
$statementRegion->execute(array($regionID));
while($rowRegion = $statementRegion->fetch())
{
return $rowRegion['regionName'];
}
return "Unknown Region";
}
public function getPartner($userID)
{
global $RUNTIME;
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM userprofile WHERE useruuid = ?");
$statement->execute(array($userID));
while($row = $statement->fetch())
{
if($row['profilePartner'] != "00000000-0000-0000-0000-000000000000")
return $row['profilePartner'];
}
return null;
}
public function allowOfflineIM($userID)
{
global $RUNTIME;
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM usersettings WHERE useruuid = ?");
$statement->execute(array($userID));
while($row = $statement->fetch())
{
return strtoupper($row['imviaemail']);
}
return "FALSE";
}
public function getUserMail($userID)
{
global $RUNTIME;
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts WHERE PrincipalID = ?");
$statement->execute(array($userID));
while($row = $statement->fetch())
{
return $row['Email'];
}
return "";
}
public function getUserCount()
{
global $RUNTIME;
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts");
$statementUser->execute();
return $statementUser->rowCount();
}
public function getRegionCount()
{
global $RUNTIME;
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM regions");
$statementUser->execute();
return $statementUser->rowCount();
}
public function getOnlineCount()
{
global $RUNTIME;
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM Presence");
$statementUser->execute();
return $statementUser->rowCount();
}
}
?>

42
classen/utils.php Normal file
View File

@ -0,0 +1,42 @@
<?php
function fillString($string, $targetlength)
{
while(strlen($string) < $targetlength)
{
$string = "0".$string;
}
return $string;
}
function left($str, $length)
{
return substr($str, 0, $length);
}
function right($str, $length)
{
return substr($str, -$length);
}
function getDataFromHTTP($URL, $contend = "", $requestTyp = "application/text")
{
try
{
if($contend != "")
{
return @file_get_contents($URL, true, stream_context_create(array('http' => array('header' => 'Content-type: '.$requestTyp, 'method' => 'POST', 'timeout' => 0.5, 'content' => $contend))));
}else{
return @file_get_contents($URL);
}
} catch (Exception $e) {
echo "(HTTP REQUEST) error while conntect to remote server. : ".$URL;
}
}
function sendInworldIM($fromUUID, $toUUID, $fromName, $targetURL, $text)
{
$rawXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodCall><methodName>grid_instant_message</methodName><params><param><value><struct><member><name>position_x</name><value><string>0</string></value></member><member><name>position_y</name><value><string>0</string></value></member><member><name>position_z</name><value><string>0</string></value></member><member><name>to_agent_id</name><value><string>".$toUUID."</string></value></member><member><name>from_agent_session</name><value><string>00000000-0000-0000-0000-000000000000</string></value></member><member><name>im_session_id</name><value><string>".$fromUUID."</string></value></member><member><name>from_agent_name</name><value><string>".$fromName."</string></value></member><member><name>from_agent_id</name><value><string>".$fromUUID."</string></value></member><member><name>binary_bucket</name><value><string>AA==</string></value></member><member><name>region_handle</name><value><i4>0</i4></value></member><member><name>region_id</name><value><string>00000000-0000-0000-0000-000000000000</string></value></member><member><name>parent_estate_id</name><value><string>1</string></value></member><member><name>timestamp</name><value><string>".time()."</string></value></member><member><name>dialog</name><value><string>AA==</string></value></member><member><name>offline</name><value><string>AA==</string></value></member><member><name>from_group</name><value><string>FALSE</string></value></member><member><name>message</name><value><string>".$text."</string></value></member></struct></value></param></params></methodCall>";
getDataFromHTTP($targetURL, $rawXML, "text/xml");
}
?>

13
config.example.php Normal file
View File

@ -0,0 +1,13 @@
<?php
$RUNTIME['PDO'] = new PDO('mysql:host=...;dbname=...', '...', '...'); //The Robust DB
$RUNTIME['SMTP']['SERVER'] = "localhost";
$RUNTIME['SMTP']['PORT'] = 25;
$RUNTIME['SMTP']['ADRESS'] = "noreplay@localhost";
$RUNTIME['SMTP']['USER'] = "noreplay@localhost";
$RUNTIME['SMTP']['PASS'] = "...";
$RUNTIME['GRID']['NAME'] = "OpenSim";
$RUNTIME['GRID']['MAIN_NEWS'] = "Yet an other OpenSim Grid.";
$RUNTIME['GRID']['HOMEURL'] = "http://...:8002";
?>

29
cron/checkInventar.php Normal file
View File

@ -0,0 +1,29 @@
<?php
$InventarObjektStatement = $RUNTIME['PDO']->prepare("SELECT * FROM inventoryitems ORDER BY avatarID ASC LIMIT 50000");
$InventarObjektStatement->execute();
while($InventarObjektRow = $InventarObjektStatement->fetch())
{
//echo "Check Inventory Item '".$InventarObjektRow['inventoryName']."' from '".$InventarObjektRow['avatarID']."'.\n";
$AssetMetaDataStatement = $RUNTIME['PDO']->prepare("SELECT * FROM fsassets WHERE id = ?");
$AssetMetaDataStatement->execute(array($InventarObjektRow['assetID']));
if($AssetMetaDataStatement->rowCount() == 0)
{
if(!(left($InventarObjektRow['inventoryName'], 8) == '[DEFEKT]'))
{
$renameQuery = $RUNTIME['PDO']->prepare("UPDATE inventoryitems SET inventoryName = ? WHERE inventoryID = ? AND assetID = ?");
$renameQuery->execute(array(substr('[DEFEKT] '.$InventarObjektRow['inventoryName'], 0, 64), $InventarObjektRow['inventoryID'], $InventarObjektRow['assetID']));
echo "Found new missing asset for item '".$InventarObjektRow['inventoryName']."' from '".$RUNTIME['OPENSIM']->getUserName($InventarObjektRow['avatarID'])."'.\n";
sendInworldIM("00000000-0000-0000-0000-000000000000", $InventarObjektRow['avatarID'], "Inventory", $RUNTIME['GRID']['HOMEURL'], "WARNUNG: Die Assetdaten von einem deiner Inventarobjekte wurden nicht in der DB gefunden! Item Name: '".$InventarObjektRow['inventoryName']."'.");
}else{
echo "Found missing asset for item '".$InventarObjektRow['inventoryName']."' from '".$RUNTIME['OPENSIM']->getUserName($InventarObjektRow['avatarID'])."'.\n";
}
}else{
echo "Checking asset for item '".$InventarObjektRow['inventoryName']."' from '".$RUNTIME['OPENSIM']->getUserName($InventarObjektRow['avatarID'])."'.\n";
}
}
?>

102
cron/offlineIM.php Normal file
View File

@ -0,0 +1,102 @@
<?php
$statement = $RUNTIME['PDO']->prepare("CREATE TABLE IF NOT EXISTS im_offline_send (`id` int(6) NOT NULL DEFAULT 0) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci");
$statement->execute();
function isMailAllreadySend($id)
{
GLOBAL $RUNTIME;
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM im_offline_send WHERE id = ?");
$statement->execute(array($id));
if($statement->rowCount() != 0)
return TRUE;
return FALSE;
}
$IMTYP = array(
"0" => "eine Nachricht",
"3" => "eine Gruppeneinladung",
"4" => "ein Inventaritem",
"5" => "eine Bestätigung zur Annahme von Inventar",
"6" => "eine Information zur Ablehnung von Inventar",
"7" => "eine Aufforderung zur Gruppenwahl",
"9" => "ein Inventaritem von einem Script",
"19" => "eine Nachricht von einem Script",
"32" => "eine Gruppennachricht",
"38" => "eine Freundschaftsanfrage",
"39" => "eine Bestätigung über die Annahme der Freundschaft",
"40" => "eine Information über das Ablehnen der Freundschaft"
);
//$statement = $RUNTIME['PDO']->prepare("SELECT * FROM im_offline WHERE PrincipalID = '1148b04d-7a93-49e9-b3c9-ea0cdeec38f7'");
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM im_offline");
$statement->execute();
while($row = $statement->fetch())
{
$email = $RUNTIME['OPENSIM']->getUserMail($row['PrincipalID']);
$allowOfflineIM = $RUNTIME['OPENSIM']->allowOfflineIM($row['PrincipalID']);
if($email != "" && $allowOfflineIM == "TRUE")
{
if(isMailAllreadySend($row['ID']) == FALSE)
{
$statementSend = $RUNTIME['PDO']->prepare('INSERT INTO im_offline_send (id) VALUES (:idnummer)');
$statementSend->execute(['idnummer' => $row['ID']]);
$mail = new PHPMailer(true);
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->isSMTP();
$mail->Host = $RUNTIME['SMTP']['SERVER'];
$mail->SMTPAuth = true;
$mail->Username = $RUNTIME['SMTP']['USER'];
$mail->Password = $RUNTIME['SMTP']['PASS'];
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = $RUNTIME['SMTP']['PORT'];
$mail->setFrom($RUNTIME['SMTP']['ADRESS'], $RUNTIME['GRID']['NAME']);
$mail->addAddress($email, $RUNTIME['OPENSIM']->getUserName($row['PrincipalID']));
$XMLMESSAGE = new SimpleXMLElement($row['Message']);
$HTMLMESSAGE = "Du hast ".$IMTYP["".$XMLMESSAGE->dialog.""]." in ".$RUNTIME['GRID']['NAME']." bekommen. <br><p><ul><li>".htmlspecialchars($XMLMESSAGE->message)."</li></ul></p>Gesendet von: ";
if(isset($XMLMESSAGE->fromAgentName))
$HTMLMESSAGE .= $XMLMESSAGE->fromAgentName;
if(isset($XMLMESSAGE->RegionID) && isset($XMLMESSAGE->Position))
{
if($XMLMESSAGE->Position->X != 0 || $XMLMESSAGE->Position->X != 0 || $XMLMESSAGE->Position->X != 0)
{
$HTMLMESSAGE .= " @ ".$RUNTIME['OPENSIM']->getRegionName($XMLMESSAGE->RegionID)."/".$XMLMESSAGE->Position->X."/".$XMLMESSAGE->Position->Y."/".$XMLMESSAGE->Position->Z;
}else{
$HTMLMESSAGE .= " @ ".$RUNTIME['OPENSIM']->getRegionName($XMLMESSAGE->RegionID);
}
}
//die($HTMLMESSAGE);
$HTML = new HTML();
$HTML->importHTML("style/mail.html");
$HTML->setSeitenInhalt($HTMLMESSAGE);
$HTML->build();
$mail->isHTML(true);
$mail->Subject = "Du hast ".$IMTYP["".$XMLMESSAGE->dialog.""]." in ".$RUNTIME['GRID']['NAME'].".";
$mail->Body = $HTML->ausgabe();
$mail->AltBody = strip_tags($HTMLMESSAGE);
//print_r($mail);
$mail->send();
}else{
//echo $row['ID']." wurde bereits gesendet.";
}
}else{
//echo $row['PrincipalID']." möchte keine offline IM oder hat keine E-MAIL Adresse hinterlegt.";
}
}
?>

34
crone.php Normal file
View File

@ -0,0 +1,34 @@
<?php
date_default_timezone_set("Europe/Berlin");
header('Strict-Transport-Security: max-age=657000');
error_reporting(E_ALL);
session_start();
include_once 'classen/MAIL/PHPMailer.php';
include_once 'classen/MAIL/SMTP.php';
include_once("classen/utils.php");
include_once("classen/HTML.php");
include_once("classen/GoogleAuthenticator.php");
include_once("classen/OpenSim.php");
$RUNTIME = array();
$RUNTIME['OPENSIM'] = new OpenSim();
include_once("config.php");
if ($handle = opendir('./cron/'))
{
while (false !== ($entry = readdir($handle)))
{
if ($entry != "." && $entry != "..")
{
include_once "./cron/".$entry;
}
}
closedir($handle);
}
?>

0
data/tmp/.keep Normal file
View File

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"54.1","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"6088","AtvPrm":"0","AtvScr":"246","ScrLPS":"39.34","PktsIn":"13","PktOut":"210","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"234","Uptime":"09:42:09.8938510","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"3182","Mesh Objects":"2906","XEngine Thread Count":"5","Util Thread Count":"3","System Thread Count":"1","ProcMem":"884,304"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"8416","AtvPrm":"0","AtvScr":"293","ScrLPS":"186.66","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0.59","OthrFt":"0.01","AgntFt":"0","ImgsFt":"0","Memory":"84","Uptime":"01:06:11.6632650","Version":"OpenSim 0.9.2.0.05 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"2868","Mesh Objects":"5548","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"419,948"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"54.9","PhyFPS":"52.2","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"7258","AtvPrm":"0","AtvScr":"492","ScrLPS":"271.85","PktsIn":"9","PktOut":"38","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.21","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"247","Uptime":"09:42:24.3060582","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"4045","Mesh Objects":"3213","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"727,100"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"0","AtvPrm":"0","AtvScr":"0","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"11","Uptime":"01:37:09.3444630","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"0","Mesh Objects":"0","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"130,996"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"52.2","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"1472","AtvPrm":"0","AtvScr":"80","ScrLPS":"29.65","PktsIn":"11","PktOut":"12","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.19","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"32","Uptime":"2.18:08:48.7446913","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"1411","Mesh Objects":"61","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"96,288"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"54.9","PhyFPS":"52.2","AgntUp":"0","RootAg":"5","ChldAg":"0","Prims":"6518","AtvPrm":"0","AtvScr":"358","ScrLPS":"511.42","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.22","NetFt":"0","PhysFt":"0.01","OthrFt":"0.03","AgntFt":"0","ImgsFt":"0","Memory":"129","Uptime":"09:42:39.2045040","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"3382","Mesh Objects":"3136","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"303,228"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"322","AtvPrm":"0","AtvScr":"31","ScrLPS":"5","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"26","Uptime":"00:37:32.8217740","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"46","Mesh Objects":"276","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"152,316"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"52.2","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"31674","AtvPrm":"0","AtvScr":"588","ScrLPS":"27.08","PktsIn":"18","PktOut":"109","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.19","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"433","Uptime":"3.13:59:59.6505372","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"25395","Mesh Objects":"6279","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"766,840"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"4214","AtvPrm":"0","AtvScr":"50","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0.02","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"103","Uptime":"00:17:43.2901890","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"4093","Mesh Objects":"121","XEngine Thread Count":"0","Util Thread Count":"5","System Thread Count":"0","ProcMem":"344,652"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"54.8","PhyFPS":"52.1","AgntUp":"9.29","RootAg":"7","ChldAg":"0","Prims":"27102","AtvPrm":"0","AtvScr":"1565","ScrLPS":"37.48","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.25","NetFt":"0","PhysFt":"0.01","OthrFt":"0.12","AgntFt":"0.46","ImgsFt":"0","Memory":"611","Uptime":"3.13:57:45.1766615","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"17068","Mesh Objects":"10034","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"4","ProcMem":"787,972"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55.2","PhyFPS":"52.4","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"407","AtvPrm":"0","AtvScr":"-9","ScrLPS":"0","PktsIn":"21","PktOut":"5","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.12","NetFt":"0","PhysFt":"0","OthrFt":"0.02","AgntFt":"0","ImgsFt":"0","Memory":"17","Uptime":"3.14:15:40.0902327","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"258","Mesh Objects":"149","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"68,496"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"53.8","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"6","AtvPrm":"0","AtvScr":"3","ScrLPS":"0","PktsIn":"22","PktOut":"125","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"12","Uptime":"09:35:02.8857695","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"6","Mesh Objects":"0","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"100,708"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"45.5","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"1531","AtvPrm":"0","AtvScr":"18","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0.04","AgntFt":"0","ImgsFt":"0","Memory":"61","Uptime":"2.18:50:04.2946060","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"1413","Mesh Objects":"118","XEngine Thread Count":"0","Util Thread Count":"4","System Thread Count":"1","ProcMem":"141,532"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"1","ChldAg":"0","Prims":"510","AtvPrm":"0","AtvScr":"37","ScrLPS":"16.99","PktsIn":"2","PktOut":"1","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0.01","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"24","Uptime":"01:36:38.4254190","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"217","Mesh Objects":"293","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"181,164"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"0","AtvPrm":"0","AtvScr":"0","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.19","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"11","Uptime":"00:37:27.4469320","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"0","Mesh Objects":"0","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"115,048"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"4214","AtvPrm":"0","AtvScr":"50","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0.01","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"108","Uptime":"00:17:48.0557620","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"4093","Mesh Objects":"121","XEngine Thread Count":"0","Util Thread Count":"5","System Thread Count":"0","ProcMem":"344,652"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"4160","AtvPrm":"0","AtvScr":"0","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"40","Uptime":"01:37:03.0917460","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"1617","Mesh Objects":"2543","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"225,808"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"45.5","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"1531","AtvPrm":"0","AtvScr":"18","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0.04","AgntFt":"0","ImgsFt":"0","Memory":"85","Uptime":"2.18:50:06.6707772","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"1413","Mesh Objects":"118","XEngine Thread Count":"0","Util Thread Count":"4","System Thread Count":"3","ProcMem":"136,644"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"4160","AtvPrm":"0","AtvScr":"0","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"41","Uptime":"00:37:33.1846060","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"1617","Mesh Objects":"2543","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"0","ProcMem":"229,888"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55.2","PhyFPS":"54","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"6124","AtvPrm":"0","AtvScr":"370","ScrLPS":"1055.39","PktsIn":"11","PktOut":"187","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.12","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"304","Uptime":"09:42:04.1113902","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"2014","Mesh Objects":"4110","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"872,408"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"53.8","AgntUp":"0","RootAg":"2","ChldAg":"0","Prims":"9533","AtvPrm":"0","AtvScr":"344","ScrLPS":"143.6","PktsIn":"15","PktOut":"205","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0.01","OthrFt":"0.01","AgntFt":"0","ImgsFt":"0","Memory":"183","Uptime":"09:34:54.2774399","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"7261","Mesh Objects":"2272","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"502,532"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"54","AgntUp":"222.11","RootAg":"5","ChldAg":"0","Prims":"60159","AtvPrm":"0","AtvScr":"2959","ScrLPS":"1038.3","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.19","NetFt":"0","PhysFt":"0.01","OthrFt":"0.03","AgntFt":"0.02","ImgsFt":"0","Memory":"1757","Uptime":"09:42:43.7007040","Version":"OpenSim 0.9.2.0.02 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"20819","Mesh Objects":"39340","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"3,293,856"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"53.9","PhyFPS":"49.7","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"21568","AtvPrm":"0","AtvScr":"1226","ScrLPS":"290.71","PktsIn":"46","PktOut":"41","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.55","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"1138","Uptime":"14:22:36.3878739","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"5440","Mesh Objects":"16128","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"3","ProcMem":"1,914,624"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55.3","PhyFPS":"52.5","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"7079","AtvPrm":"0","AtvScr":"608","ScrLPS":"23.32","PktsIn":"18","PktOut":"17","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.1","NetFt":"0","PhysFt":"0","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"219","Uptime":"2.18:28:44.6906436","Version":"OpenSim 0.9.2.0.04 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"4369","Mesh Objects":"2710","XEngine Thread Count":"0","Util Thread Count":"3","System Thread Count":"1","ProcMem":"391,580"}

View File

@ -0,0 +1 @@
{"Dilatn":"1","SimFPS":"55","PhyFPS":"55","AgntUp":"0","RootAg":"0","ChldAg":"0","Prims":"4214","AtvPrm":"0","AtvScr":"50","ScrLPS":"0","PktsIn":"0","PktOut":"0","PendDl":"0","PendUl":"0","UnackB":"0","TotlFt":"18.18","NetFt":"0","PhysFt":"0.01","OthrFt":"0","AgntFt":"0","ImgsFt":"0","Memory":"104","Uptime":"00:17:45.6773380","Version":"OpenSim 0.9.2.0.06 Yeti Dev ","FrameDilatn":"1","Logging in Users":"0","GeoPrims":"4093","Mesh Objects":"121","XEngine Thread Count":"0","Util Thread Count":"5","System Thread Count":"0","ProcMem":"344,652"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

65
index.php Normal file
View File

@ -0,0 +1,65 @@
<?php
date_default_timezone_set("Europe/Berlin");
header('Strict-Transport-Security: max-age=657000');
error_reporting(E_ALL);
session_start();
include_once 'classen/MAIL/PHPMailer.php';
include_once 'classen/MAIL/SMTP.php';
include_once("classen/utils.php");
include_once("classen/HTML.php");
include_once("classen/GoogleAuthenticator.php");
include_once("classen/OpenSim.php");
$RUNTIME = array();
$RUNTIME['OPENSIM'] = new OpenSim();
include_once("config.php");
if(isset($_REQUEST['api']))
{
if(file_exists("./api/".$_REQUEST['api'].".php")){
if($_REQUEST['api'] == str_replace("/"," ",$_REQUEST['api']) and $_REQUEST['api'] == str_replace("\\"," ",$_REQUEST['api']) and $_REQUEST['api'] == str_replace(".."," ",$_REQUEST['api'])){
include "./api/".$_REQUEST['api'].".php";
}else{
die("ERROR; ENDPOINT NOT EXIST");
}
}else{
die("ERROR; ENDPOINT NOT EXIST");
}
die();
}
if(isset($_REQUEST['logout']))
if($_REQUEST['logout'] == '1')
$_SESSION = array();
if(isset($_SESSION['LOGIN']))
if($_SESSION['LOGIN'] == 'true')
{
if(!isset($_REQUEST['page']))
$_REQUEST['page'] = 'dashboard';
if(file_exists("./pages/".$_REQUEST['page'].".php")){
if($_REQUEST['page'] == str_replace("/"," ",$_REQUEST['page']) and $_REQUEST['page'] == str_replace("\\"," ",$_REQUEST['page']) and $_REQUEST['page'] == str_replace(".."," ",$_REQUEST['page'])){
include "./pages/".$_REQUEST['page'].".php";
}else{
include "./pages/error.php";
}
}else{
include "./pages/error.php";
}
die();
}
if(@$_REQUEST['page'] == "register")
{
include "./pages/register.php";
}else{
include "./pages/login.php";
}
?>

1
pages/.htaccess Normal file
View File

@ -0,0 +1 @@
Deny from all

33
pages/HTML/dashboard.html Normal file
View File

@ -0,0 +1,33 @@
<div class="row">
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-primary o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fas fa-fw fa-door-closed"></i>
</div>
<div class="mr-5">%%GLOBAL-USER-COUNT%%</div>
</div>
<span class="card-footer text-white clearfix small z-1 float-left">Benutzer / Online</span>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
</div>
<div class="col-xl-3 col-sm-6 mb-3">
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-primary o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fas fa-fw fa-thermometer-half"></i>
</div>
<div class="mr-5">%%GLOBAL-REGION-COUNT%%</div>
</div>
<span class="card-footer text-white clearfix small z-1 float-left">Regionen</span>
</div>
</div>
</div>

View File

@ -0,0 +1 @@
%%REGION-LIST%%

View File

@ -0,0 +1 @@
%%ONLINE-LIST%%

163
pages/HTML/profile.html Normal file
View File

@ -0,0 +1,163 @@
<div style="width: 400px; margin: auto; left: 50%;">
<form action="index.php?page=profile" method="post">
<div class="row">
<div class="col">
<label for="inputVorname">Vorname</label>
<input type="text" class="form-control" id="inputVorname" name="formInputFeldVorname" placeholder="%%firstname%%">
</div>
<div class="col">
<label for="inputNachname">Nachname</label>
<input type="text" class="form-control" id="inputNachname" name="formInputFeldNachname" placeholder="%%lastname%%">
</div>
</div>
<div class="row" style="margin-top: 15px;">
<div class="col">
<label for="inputVorname">E-Mail</label>
<input type="text" class="form-control" id="inputEmail" name="formInputFeldEMail" placeholder="%%email%%">
</div>
</div>
<div class="form-group" style="margin-top: 15px;">
<div class="form-check">
<input class="form-check-input" name="formInputFeldOfflineIM" type="checkbox" id="gridCheck"%%offlineIMSTATE%%>
<label class="form-check-label" for="gridCheck"> Offline IM</label>
</div>
</div>
<div class="row" style="margin-top: 15px;">
<div class="col">
<hr>
</div>
</div>
<div class="row" style="margin-top: 15px;">
<div class="col">
<label for="dropdownPartner">Partner</label>
<input type="text" class="form-control" name="formInputFeldPartnerName" id="inputpartner" placeholder="%%partner%%">
</div>
</div>
<div class="row" style="margin-top: 15px;">
<div class="col">
<hr>
</div>
</div>
<div class="row" style="margin-top: 15px;">
<div class="col">
<button type="submit" name="saveProfileData" class="btn btn-primary btn-lg">Speichern</button>
</div>
</div>
</form>
</div>
<script>
var countries = [%%listAllResidentsAsJSArray%%];
function autocomplete(inp, arr) {
/*the autocomplete function takes two arguments,
the text field element and an array of possible autocompleted values:*/
var currentFocus;
/*execute a function when someone writes in the text field:*/
inp.addEventListener("input", function(e) {
var a, b, i, val = this.value;
/*close any already open lists of autocompleted values*/
closeAllLists();
if (!val) {
return false;
}
currentFocus = -1;
/*create a DIV element that will contain the items (values):*/
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
/*append the DIV element as a child of the autocomplete container:*/
this.parentNode.appendChild(a);
/*for each item in the array...*/
for (i = 0; i < arr.length; i++) {
/*check if the item starts with the same letters as the text field value:*/
if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) {
/*create a DIV element for each matching element:*/
b = document.createElement("DIV");
/*make the matching letters bold:*/
b.innerHTML = "<strong>" + arr[i].substr(0, val.length) + "</strong>";
b.innerHTML += arr[i].substr(val.length);
/*insert a input field that will hold the current array item's value:*/
b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
/*execute a function when someone clicks on the item value (DIV element):*/
b.addEventListener("click", function(e) {
/*insert the value for the autocomplete text field:*/
inp.value = this.getElementsByTagName("input")[0].value;
/*close the list of autocompleted values,
(or any other open lists of autocompleted values:*/
closeAllLists();
});
a.appendChild(b);
}
}
});
/*execute a function presses a key on the keyboard:*/
inp.addEventListener("keydown", function(e) {
var x = document.getElementById(this.id + "autocomplete-list");
if (x) x = x.getElementsByTagName("div");
if (e.keyCode == 40) {
/*If the arrow DOWN key is pressed,
increase the currentFocus variable:*/
currentFocus++;
/*and and make the current item more visible:*/
addActive(x);
} else if (e.keyCode == 38) { //up
/*If the arrow UP key is pressed,
decrease the currentFocus variable:*/
currentFocus--;
/*and and make the current item more visible:*/
addActive(x);
} else if (e.keyCode == 13) {
/*If the ENTER key is pressed, prevent the form from being submitted,*/
e.preventDefault();
if (currentFocus > -1) {
/*and simulate a click on the "active" item:*/
if (x) x[currentFocus].click();
}
}
});
function addActive(x) {
/*a function to classify an item as "active":*/
if (!x) return false;
/*start by removing the "active" class on all items:*/
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = (x.length - 1);
/*add class "autocomplete-active":*/
x[currentFocus].classList.add("autocomplete-active");
}
function removeActive(x) {
/*a function to remove the "active" class from all autocomplete items:*/
for (var i = 0; i < x.length; i++) {
x[i].classList.remove("autocomplete-active");
}
}
function closeAllLists(elmnt) {
/*close all autocomplete lists in the document,
except the one passed as an argument:*/
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (elmnt != x[i] && elmnt != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
/*execute a function when someone clicks in the document:*/
document.addEventListener("click", function(e) {
closeAllLists(e.target);
});
}
autocomplete(document.getElementById("inputpartner"), countries);
</script>

View File

@ -0,0 +1,202 @@
<html>
<head>
<style>
body {
background-color: rgb(0, 0, 0);
width: 100%;
height: 100%;
overflow: hidden;
font-family: 'Arial';
font-size: 11px;
padding: 0;
margin: 0;
}
.InfoBox {
width: 300px;
height: auto;
background: rgba(0, 0, 0, 0.85);
color: rgb(220, 220, 220);
padding: 10px;
}
.InfoBox a {
color: rgb(220, 220, 220);
text-decoration: underline;
}
.InfoBox a:hover {
color: rgb(255, 255, 255);
text-decoration: underline;
}
.InfoBoxTitle {
width: 100%;
height: auto;
padding: 0;
padding-bottom: 5px;
margin-bottom: 5px;
border: 0px dashed rgb(128, 128, 128);
border-bottom-width: 1px;
color: rgb(220, 220, 220);
font-weight: bold;
font-size: 14px;
}
.GridLogo {
position: absolute;
top: 50px;
left: 50px;
border: 0;
}
.ScrollBar::-webkit-scrollbar {
width: 3px;
}
.ScrollBar::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
.ScrollBar::-webkit-scrollbar-thumb {
background: rgba(38, 38, 38, 0.9);
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<img src='' style='border: 0; display: block; opacity; 0; position: absolute;' id='Image1' />
<img src='' style='border: 0; display: block; opacity: 0; position: absolute;' id='Image2' />
<script type='text/javascript'>
var Images = %%JSONIMAGEARRAY%%;
var MakeAnimation = true;
var CurrentIndex = 2;
var CurrentImage = -1;
var ImageTimeout = 0;
var CurrentImageTranslation = -1;
var ImagePositions = [{'x': -50, 'y': -50, 'px': 1, 'py': 1},
{'x': -50, 'y': -50, 'px': 1, 'py': 1}];
document.getElementById('Image1').onload = function() {
if (MakeAnimation)
{
this.style.width = (window.innerWidth + 100) + 'px';
if (this.offsetHeight < window.innerHeight + 100)
{
this.style.width = null;
this.style.height = (window.innerHeight + 100) + 'px';
}
ImagePositions[0].x = -50;
ImagePositions[0].y = -50;
}
else
{
this.style.width = window.innerWidth + 'px';
if (this.offsetHeight < window.innerHeight)
{
this.style.width = null;
this.style.height = window.innerHeight + 'px';
}
ImagePositions[0].x = 0;
ImagePositions[0].y = 0;
}
CurrentImageTranslation = 0;
};
document.getElementById('Image2').onload = function() {
if (MakeAnimation)
{
this.style.width = (window.innerWidth + 100) + 'px';
if (this.offsetHeight < window.innerHeight + 100)
{
this.style.width = null;
this.style.height = (window.innerHeight + 100) + 'px';
}
ImagePositions[1].x = -50;
ImagePositions[1].y = -50;
}
else
{
this.style.width = window.innerWidth + 'px';
if (this.offsetHeight < window.innerHeight)
{
this.style.width = null;
this.style.height = window.innerHeight + 'px';
}
ImagePositions[0].x = 0;
ImagePositions[0].y = 0;
}
CurrentImageTranslation = 0;
};
window.setInterval(function() {
ImageTimeout = ImageTimeout - 1;
if (ImageTimeout <= 0)
{
ImageTimeout = 10;
CurrentImage = CurrentImage + 1;
if (CurrentImage >= Images.length)
{CurrentImage = 0;}
if (CurrentIndex == 1)
{CurrentIndex = 2;}
else
{CurrentIndex = 1;}
document.getElementById('Image' + CurrentIndex).style.width = null;
document.getElementById('Image' + CurrentIndex).style.height = null;
document.getElementById('Image' + CurrentIndex).src = Images[CurrentImage];
}
}, 1000);
window.setInterval(function() {
if (MakeAnimation)
{
for (var i = 0; i < 2; ++i)
{
ImagePositions[i].x = ImagePositions[i].x + ImagePositions[i].px;
ImagePositions[i].y = ImagePositions[i].y + ImagePositions[i].py;
var OffWidth = document.getElementById('Image' + (i + 1)).offsetWidth;
var OffHeight = document.getElementById('Image' + (i + 1)).offsetHeight;
if (ImagePositions[i].x >= 0 || ImagePositions[i].x + OffWidth <= window.innerWidth)
{ImagePositions[i].px = -ImagePositions[i].px;}
if (ImagePositions[i].y >= 0 || ImagePositions[i].y + OffHeight <= window.innerHeight)
{ImagePositions[i].py = -ImagePositions[i].py;}
document.getElementById('Image' + (i + 1)).style.left = ImagePositions[i].x + 'px';
document.getElementById('Image' + (i + 1)).style.top = ImagePositions[i].y + 'px';
}
}
if (CurrentImageTranslation > -1)
{
var DoReset = false;
CurrentImageTranslation = CurrentImageTranslation + 0.025;
if (CurrentImageTranslation >= 1.0)
{
CurrentImageTranslation = 1.0;
DoReset = true;
}
if (CurrentIndex == 1)
{
document.getElementById('Image1').style.opacity = CurrentImageTranslation;
document.getElementById('Image2').style.opacity = 1 - CurrentImageTranslation;
}
else
{
document.getElementById('Image2').style.opacity = CurrentImageTranslation;
document.getElementById('Image1').style.opacity = 1 - CurrentImageTranslation;
}
if (DoReset)
{CurrentImageTranslation = -1;}
}
}, 50);
</script>
<div class='InfoBox' style='position: absolute; right: 50px; top: 50px;'>
<div class='InfoBoxTitle'>%%GRIDNAME%%</div>
Willkommen<br />
Bitte melde dich an, um %%GRIDNAME%% zu betreten.<br />
<br />
%%SHOWNEWS%%
</div>
<div class='InfoBox' style='position: absolute; left: 50px; bottom: 50px;'>
<div class='InfoBoxTitle'>
Status: <span style='color: rgb(0, 255, 0);'>Online</span>
</div>
%%SHOWSTATS%%
</div>
</body>
</html>

15
pages/dashboard.php Normal file
View File

@ -0,0 +1,15 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Dashboard");
$HTML->importHTML("style/default/dashboard.html");
$HTML->importSeitenInhalt("pages/HTML/dashboard.html");
$HTML->ReplaceSeitenInhalt("%%GLOBAL-USER-COUNT%%", $RUNTIME['OPENSIM']->getUserCount());
$HTML->ReplaceSeitenInhalt("%%GLOBAL-REGION-COUNT%%", $RUNTIME['OPENSIM']->getRegionCount());
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->build();
echo $HTML->ausgabe();
?>

11
pages/error.php Normal file
View File

@ -0,0 +1,11 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Seite nicht gefunden");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->build();
header("HTTP/1.0 404 Not Found");
echo $HTML->ausgabe();
?>

31
pages/groups.php Normal file
View File

@ -0,0 +1,31 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Gruppen");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->importSeitenInhalt("pages/HTML/deine-regionen.html");
$table = '<table class="table"><thead><tr><th scope="col">Name</th><th scope="col">Gründer</th><th scope="col">Aktionen</th></thead><tbody>%%ENTRY%%</tbody></table>';
$statementMembership = $RUNTIME['PDO']->prepare("SELECT * FROM os_groups_membership WHERE PrincipalID = ? ORDER BY GroupID ASC");
$statementMembership->execute(array($_SESSION['UUID']));
while($rowMembership = $statementMembership->fetch())
{
$statementGroups = $RUNTIME['PDO']->prepare("SELECT * FROM os_groups_groups WHERE GroupID = ? LIMIT 1");
$statementGroups->execute(array($rowMembership['GroupID']));
while($rowGroups = $statementGroups->fetch())
{
$entry = '<tr><td>'.$rowGroups['Name'].'</td><td>'.$RUNTIME['OPENSIM']->getUserName($rowGroups['FounderID']).'</td><td>VERLASSEN</td></tr>';
$table = str_replace("%%ENTRY%%", $entry."%%ENTRY%%", $table);
}
}
$table = str_replace("%%ENTRY%%", "", $table);
$HTML->ReplaceSeitenInhalt("%%REGION-LIST%%", $table);
$HTML->build();
echo $HTML->ausgabe();
?>

58
pages/login.php Normal file
View File

@ -0,0 +1,58 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Login");
$HTML->importHTML("style/login/login.html");
if(isset($_POST['login']))
{
if(!isset($_POST['username']) || !isset($_POST['password']))
{
$HTML->ReplaceLayoutInhalt("%%LOGINMESSAGE%%", "Bitte gebe Benutzername und Passwort an.");
}else{
$statementUser = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts WHERE FirstName = ? AND LastName = ? LIMIT 1");
$statementUser->execute(explode(" ", trim($_POST['username'])));
$RUNTIME['MESSAGE']['LOGINERROR'] = "Benutzername nicht gefunden!";
while($rowUser = $statementUser->fetch())
{
$statementAuth = $RUNTIME['PDO']->prepare("SELECT * FROM auth WHERE UUID = ? LIMIT 1");
$statementAuth->execute(array($rowUser['PrincipalID']));
$RUNTIME['DEBUG']['LOGIN']['UUID'] = $rowUser['PrincipalID'];
while($rowAuth = $statementAuth->fetch())
{
if(md5(md5($_POST['password']).":".$rowAuth['passwordSalt']) == $rowAuth['passwordHash'])
{
$_SESSION['USERNAME'] = trim($_POST['username']);
$_SESSION['FIRSTNAME'] = trim($rowUser['FirstName']);
$_SESSION['LASTNAME'] = trim($rowUser['LastName']);
$_SESSION['EMAIL'] = trim($rowUser['Email']);
$_SESSION['UUID'] = $rowUser['PrincipalID'];
$_SESSION['LEVEL'] = $rowUser['UserLevel'];
$_SESSION['DISPLAYNAME'] = strtoupper(trim($_POST['username']));
$_SESSION['LOGIN'] = 'true';
include "./pages/".@$_REQUEST['page'].".php";
die();
}
}
$RUNTIME['MESSAGE']['LOGINERROR'] = "Passwort falsch!";
}
$HTML->ReplaceLayoutInhalt("%%LOGINMESSAGE%%", $RUNTIME['MESSAGE']['LOGINERROR']);
$HTML->ReplaceLayoutInhalt("%%LASTUSERNAME%%", $_POST['username']);
}
}
if(file_exists("./pages/".@$_REQUEST['page'].".php"))
$HTML->ReplaceLayoutInhalt("%%PAGENAME%%", @$_REQUEST['page']);
$HTML->ReplaceLayoutInhalt("%%LOGINMESSAGE%%", "");
$HTML->ReplaceLayoutInhalt("%%LASTUSERNAME%%", "");
$HTML->ReplaceLayoutInhalt("%%PAGENAME%%", "dashboard");
$HTML->build();
echo $HTML->ausgabe();
?>

139
pages/profile.php Normal file
View File

@ -0,0 +1,139 @@
<?php
if(isset($_REQUEST['formInputFeldVorname']) || @$_REQUEST['formInputFeldVorname'] != "")
{
$NewFirstName = trim($_REQUEST['formInputFeldVorname']);
if($NewFirstName != "")
{
if($_SESSION['FIRSTNAME'] != $NewFirstName)
{
$statement = $RUNTIME['PDO']->prepare('UPDATE UserAccounts SET FirstName = :FirstName WHERE PrincipalID = :PrincipalID');
$statement->execute(['FirstName' => $NewFirstName, 'PrincipalID' => $_SESSION['UUID']]);
$_SESSION['FIRSTNAME'] = $NewFirstName;
$_SESSION['USERNAME'] = $_SESSION['FIRSTNAME']." ".$_SESSION['LASTNAME'];
$_SESSION['DISPLAYNAME'] = strtoupper($_SESSION['USERNAME']);
}
}
}
if(isset($_REQUEST['formInputFeldNachname']) || @$_REQUEST['formInputFeldNachname'] != "")
{
$NewLastName = trim($_REQUEST['formInputFeldNachname']);
if($NewLastName != "")
{
if($_SESSION['LASTNAME'] != $NewLastName)
{
$statement = $RUNTIME['PDO']->prepare('UPDATE UserAccounts SET LastName = :LastName WHERE PrincipalID = :PrincipalID');
$statement->execute(['LastName' => $NewLastName, 'PrincipalID' => $_SESSION['UUID']]);
$_SESSION['LASTNAME'] = $NewLastName;
$_SESSION['USERNAME'] = $_SESSION['FIRSTNAME']." ".$_SESSION['LASTNAME'];
$_SESSION['DISPLAYNAME'] = strtoupper($_SESSION['USERNAME']);
}
}
}
if(isset($_REQUEST['formInputFeldEMail']) || @$_REQUEST['formInputFeldEMail'] != "")
{
$NewEMail = trim($_REQUEST['formInputFeldEMail']);
if($NewEMail != "")
{
if($_SESSION['EMAIL'] != $NewEMail)
{
$statement = $RUNTIME['PDO']->prepare('UPDATE UserAccounts SET Email = :Email WHERE PrincipalID = :PrincipalID');
$statement->execute(['Email' => $NewEMail, 'PrincipalID' => $_SESSION['UUID']]);
$statement = $RUNTIME['PDO']->prepare('UPDATE usersettings SET email = :Email WHERE useruuid = :PrincipalID');
$statement->execute(['Email' => $NewEMail, 'PrincipalID' => $_SESSION['UUID']]);
$_SESSION['EMAIL'] = $NewEMail;
}
}
}
if(isset($_REQUEST['formInputFeldOfflineIM']) || @$_REQUEST['formInputFeldOfflineIM'] != "")
{
$NewOfflineIM = trim($_REQUEST['formInputFeldOfflineIM']);
if($NewOfflineIM != "")
{
if($NewOfflineIM == "on" || $NewOfflineIM == "true")
{
$statement = $RUNTIME['PDO']->prepare('UPDATE usersettings SET imviaemail = :IMState WHERE useruuid = :PrincipalID');
$statement->execute(['IMState' => 'true', 'PrincipalID' => $_SESSION['UUID']]);
}
}
}else if(!isset($_REQUEST['formInputFeldOfflineIM']) && isset($_REQUEST['saveProfileData'])){
$statement = $RUNTIME['PDO']->prepare('UPDATE usersettings SET imviaemail = :IMState WHERE useruuid = :PrincipalID');
$statement->execute(['IMState' => 'false', 'PrincipalID' => $_SESSION['UUID']]);
}
if(isset($_REQUEST['formInputFeldPartnerName']) || @$_REQUEST['formInputFeldPartnerName'] != "")
{
$NewPartner = trim($_REQUEST['formInputFeldPartnerName']);
$CurrentPartner = $RUNTIME['OPENSIM']->getPartner($_SESSION['UUID']);
if($CurrentPartner != "")$CurrentPartner = $RUNTIME['OPENSIM']->getUserName($CurrentPartner);
if($NewPartner != "")
{
if($CurrentPartner != $NewPartner)
{
$newPartnerUUID = $RUNTIME['OPENSIM']->getUserUUID($NewPartner);
if($newPartnerUUID != null)
{
$statement = $RUNTIME['PDO']->prepare('UPDATE userprofile SET profilePartner = :profilePartner WHERE useruuid = :PrincipalID');
$statement->execute(['profilePartner' => $newPartnerUUID, 'PrincipalID' => $_SESSION['UUID']]);
}
}
}else{
$statement = $RUNTIME['PDO']->prepare('UPDATE userprofile SET profilePartner = :profilePartner WHERE useruuid = :PrincipalID');
$statement->execute(['profilePartner' => '00000000-0000-0000-0000-000000000000', 'PrincipalID' => $_SESSION['UUID']]);
}
}
$HTML = new HTML();
$HTML->setHTMLTitle("Dein Profile");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->importSeitenInhalt("pages/HTML/profile.html");
$statementLocalUsers = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts ORDER BY PrincipalID ASC");
$statementLocalUsers->execute();
$allUsers = "";
while($row = $statementLocalUsers->fetch())
{
$name = '"'.@$row['FirstName']." ".@$row['LastName'].'"';
if($allUsers != "")
{
$allUsers .= ",".$name;
}else{
$allUsers .= $name;
}
}
$allUsers .= '," "';
$PartnerUUID = $RUNTIME['OPENSIM']->getPartner($_SESSION['UUID']);
$PartnerName = "";
if($PartnerUUID != null)$PartnerName = $RUNTIME['OPENSIM']->getUserName($PartnerUUID);
if($RUNTIME['OPENSIM']->allowOfflineIM($_SESSION['UUID']) == "TRUE")$HTML->ReplaceSeitenInhalt("%%offlineIMSTATE%%", ' checked');
$HTML->ReplaceSeitenInhalt("%%offlineIMSTATE%%", ' ');
$HTML->ReplaceSeitenInhalt("%%firstname%%", $_SESSION['FIRSTNAME']);
$HTML->ReplaceSeitenInhalt("%%lastname%%", $_SESSION['LASTNAME']);
$HTML->ReplaceSeitenInhalt("%%partner%%", $PartnerName);
$HTML->ReplaceSeitenInhalt("%%email%%", $RUNTIME['OPENSIM']->getUserMail($_SESSION['UUID']));
$HTML->ReplaceSeitenInhalt("%%listAllResidentsAsJSArray%%", $allUsers);
$HTML->build();
echo $HTML->ausgabe();
?>

33
pages/regions.php Normal file
View File

@ -0,0 +1,33 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Deine Regionen");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->importSeitenInhalt("pages/HTML/deine-regionen.html");
$table = '<table class="table"><thead><tr><th scope="col">Region Name</th><th scope="col">Eigentümer</th><th scope="col">Position</th><th scope="col">Aktionen</th></thead><tbody>%%ENTRY%%</tbody></table>';
if(@$_SESSION['LEVEL'] > 100 && @$_REQUEST['SHOWALL'] == "1")
{
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM regions ORDER BY owner_uuid ASC");
$statement->execute(array($_SESSION['UUID']));
}else{
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM regions WHERE owner_uuid = ? ORDER BY uuid ASC");
$statement->execute(array($_SESSION['UUID']));
}
$statement->execute(array($_SESSION['UUID']));
while($row = $statement->fetch())
{
$entry = '<tr><td>'.$row['regionName'].'</td><td>'.$RUNTIME['OPENSIM']->getUserName($row['owner_uuid']).'</td><td>'.fillString(($row['locX'] / 256), 4).' / '.fillString(($row['locY'] / 256), 4).'</td><td>TELEPORT | LÖSCHEN</td></tr>';
$table = str_replace("%%ENTRY%%", $entry."%%ENTRY%%", $table);
}
$table = str_replace("%%ENTRY%%", "", $table);
$HTML->ReplaceSeitenInhalt("%%REGION-LIST%%", $table);
$HTML->build();
echo $HTML->ausgabe();
?>

View File

@ -0,0 +1,28 @@
<?php
$HTML = new HTML();
$HTML->setHTMLTitle("Online Anzeige");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->importSeitenInhalt("pages/HTML/online-anzeige.html");
$table = '<table class="table"><thead><tr><th scope="col">Benutzername</th><th scope="col">Region</th></thead><tbody>%%ENTRY%%</tbody></table>';
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM Presence ORDER BY RegionID ASC");
$statement->execute();
while($row = $statement->fetch())
{
if($row['RegionID'] != "00000000-0000-0000-0000-000000000000")
{
$entry = '<tr><td>'.trim($RUNTIME['OPENSIM']->getUserName($row['UserID'])).'</td><td>'.$RUNTIME['OPENSIM']->getRegionName($row['RegionID']).'</td></tr>';
$table = str_replace("%%ENTRY%%", $entry."%%ENTRY%%", $table);
}
}
$table = str_replace("%%ENTRY%%", "", $table);
$HTML->ReplaceSeitenInhalt("%%ONLINE-LIST%%", $table);
$HTML->build();
echo $HTML->ausgabe();
?>

38
pages/users.php Normal file
View File

@ -0,0 +1,38 @@
<?php
if(@$_SESSION['LEVEL'] < 100)
{
$HTML = new HTML();
$HTML->setHTMLTitle("Kein Zugriff");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->SetSeitenInhalt("Dazu hast du keine Rechte!");
$HTML->build();
echo $HTML->ausgabe();
die();
}else{
$HTML = new HTML();
$HTML->setHTMLTitle("Benutzer");
$HTML->importHTML("style/default/dashboard.html");
$HTML->ReplaceLayoutInhalt("%%USERNAME%%", $_SESSION['DISPLAYNAME']);
$HTML->importSeitenInhalt("pages/HTML/deine-regionen.html");
$table = '<table class="table"><thead><tr><th scope="col">Vorname</th><th scope="col">Nachname</th><th scope="col">Status</th><th scope="col">Aktionen</th></thead><tbody>%%ENTRY%%</tbody></table>';
$statement = $RUNTIME['PDO']->prepare("SELECT * FROM UserAccounts ORDER BY Created ASC");
$statement->execute();
while($row = $statement->fetch())
{
$entry = '<tr><td>'.$row['FirstName'].'</td><td>'.$row['LastName'].'</td><td>'.$row['UserLevel'].'</td><td>PASSWORT ÄNDERN | SPERREN | UMBENENNEN</td></tr>';
$table = str_replace("%%ENTRY%%", $entry."%%ENTRY%%", $table);
}
$table = str_replace("%%ENTRY%%", "", $table);
$HTML->ReplaceSeitenInhalt("%%REGION-LIST%%", $table);
$HTML->build();
echo $HTML->ausgabe();
}
?>

BIN
style/4Creative.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,40 @@
.autocomplete {
/*the container must be positioned relative:*/
position: relative;
display: inline-block;
}
input[type=text] {
background-color: #f1f1f1;
width: 100%;
}
input[type=submit] {
background-color: DodgerBlue;
color: #fff;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
/*when hovering an item:*/
background-color: #e9e9e9;
}
.autocomplete-active {
/*when navigating through the items using the arrow keys:*/
background-color: DodgerBlue !important;
color: #ffffff;
}

10914
style/default/css/sb-admin.css Normal file

File diff suppressed because it is too large Load Diff

10
style/default/css/sb-admin.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,136 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>OpenSim - Kontrollzentrum - %%USERNAME%% - %%EchoTitle%%</title>
<link href="./style/4Creative.ico" rel="icon">
<link href="./style/4Creative.ico" rel="apple-touch-icon">
<link href="./style/default/css/autocomplete.css" rel="stylesheet" type="text/css">
<link href="./style/default/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href="./style/default/vendor/datatables/dataTables.bootstrap4.css" rel="stylesheet">
<link href="./style/default/css/sb-admin.css" rel="stylesheet"> %%echoHeader%%
</head>
<body id="page-top">
<nav class="navbar navbar-expand navbar-dark bg-dark static-top">
<button class="btn btn-link btn-sm text-white order-1 order-sm-0" id="sidebarToggle" href="#">
<i class="fas fa-bars"></i>
</button>
<div class="d-none d-md-inline-block form-inline ml-auto mr-0 mr-md-3 my-2 my-md-0"></div>
<ul class="navbar-nav ml-auto ml-md-0">
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">%%USERNAME%% <i class="fas fa-user-circle fa-fw"></i></a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="userDropdown">
<a class="dropdown-item" href="?page=profil">Profil</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">Logout</a>
</div>
</li>
</ul>
</nav>
<div id="wrapper">
<ul class="sidebar navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="index.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php?page=downloads">
<i class="fas fa-link"></i>
<span>Downloads</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php?page=profile">
<i class="far fa-address-card"></i>
<span>Profil</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php?page=user-online-state">
<i class="fas fa-link"></i>
<span>Online Anzeige</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php?page=regions">
<i class="fas fa-globe-europe"></i>
<span>Deine Regionen</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php?page=users">
<i class="fas fa-user-plus"></i>
<span>Benutzer verwalten</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.php?page=groups">
<i class="fas fa-users"></i>
<span>Deine Gruppen</span></a>
</li>
</ul>
<div id="content-wrapper">
<div class="container-fluid">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="index.php">Gridverwaltung</a>
</li>
<li class="breadcrumb-item active">%%EchoTitle%%</li>
</ol>
<hr><br>
%%EchoInhalt%%
</div>
</div>
</div>
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Bist du sicher?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Wähle 'Logout' wenn du dich wirklich abmelden möchtest.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Abbrechen</button>
<a class="btn btn-primary" href="index.php?logout=1">Logout</a>
</div>
</div>
</div>
</div>
<script src="./style/default/vendor/jquery/jquery.min.js"></script>
<script src="./style/default/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="./style/default/vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="./style/default/vendor/chart.js/Chart.min.js"></script>
<script src="./style/default/vendor/datatables/jquery.dataTables.js"></script>
<script src="./style/default/vendor/datatables/dataTables.bootstrap4.js"></script>
<script src="./style/default/js/sb-admin.min.js"></script>
<script src="./style/default/js/demo/datatables-demo.js"></script>
<script src="./style/default/js/demo/chart-area-demo.js"></script>
</body>
</html>

View File

@ -0,0 +1,54 @@
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';
// Area Chart Example
var ctx = document.getElementById("myAreaChart");
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Mar 1", "Mar 2", "Mar 3", "Mar 4", "Mar 5", "Mar 6", "Mar 7", "Mar 8", "Mar 9", "Mar 10", "Mar 11", "Mar 12", "Mar 13"],
datasets: [{
label: "Sessions",
lineTension: 0.3,
backgroundColor: "rgba(2,117,216,0.2)",
borderColor: "rgba(2,117,216,1)",
pointRadius: 5,
pointBackgroundColor: "rgba(2,117,216,1)",
pointBorderColor: "rgba(255,255,255,0.8)",
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(2,117,216,1)",
pointHitRadius: 50,
pointBorderWidth: 2,
data: [10000, 30162, 26263, 18394, 18287, 28682, 31274, 33259, 25849, 24159, 32651, 31984, 38451],
}],
},
options: {
scales: {
xAxes: [{
time: {
unit: 'date'
},
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 7
}
}],
yAxes: [{
ticks: {
min: 0,
max: 40000,
maxTicksLimit: 5
},
gridLines: {
color: "rgba(0, 0, 0, .125)",
}
}],
},
legend: {
display: false
}
}
});

View File

@ -0,0 +1,46 @@
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';
// Bar Chart Example
var ctx = document.getElementById("myBarChart");
var myLineChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
label: "Revenue",
backgroundColor: "rgba(2,117,216,1)",
borderColor: "rgba(2,117,216,1)",
data: [4215, 5312, 6251, 7841, 9821, 14984],
}],
},
options: {
scales: {
xAxes: [{
time: {
unit: 'month'
},
gridLines: {
display: false
},
ticks: {
maxTicksLimit: 6
}
}],
yAxes: [{
ticks: {
min: 0,
max: 15000,
maxTicksLimit: 5
},
gridLines: {
display: true
}
}],
},
legend: {
display: false
}
}
});

View File

@ -0,0 +1,16 @@
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';
// Pie Chart Example
var ctx = document.getElementById("myPieChart");
var myPieChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["Blue", "Red", "Yellow", "Green"],
datasets: [{
data: [12.21, 15.58, 11.25, 8.32],
backgroundColor: ['#007bff', '#dc3545', '#ffc107', '#28a745'],
}],
},
});

View File

@ -0,0 +1,4 @@
// Call the dataTables jQuery plugin
$(document).ready(function() {
$('#dataTable').DataTable();
});

View File

@ -0,0 +1,40 @@
(function($) {
"use strict"; // Start of use strict
// Toggle the side navigation
$("#sidebarToggle").on('click', function(e) {
e.preventDefault();
$("body").toggleClass("sidebar-toggled");
$(".sidebar").toggleClass("toggled");
});
// Prevent the content wrapper from scrolling when the fixed side navigation hovered over
$('body.fixed-nav .sidebar').on('mousewheel DOMMouseScroll wheel', function(e) {
if ($(window).width() > 768) {
var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail;
this.scrollTop += (delta < 0 ? 1 : -1) * 30;
e.preventDefault();
}
});
// Scroll to top button appear
$(document).on('scroll', function() {
var scrollDistance = $(this).scrollTop();
if (scrollDistance > 100) {
$('.scroll-to-top').fadeIn();
} else {
$('.scroll-to-top').fadeOut();
}
});
// Smooth scrolling using jQuery easing
$(document).on('click', 'a.scroll-to-top', function(event) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: ($($anchor.attr('href')).offset().top)
}, 1000, 'easeInOutExpo');
event.preventDefault();
});
})(jQuery); // End of use strict

7
style/default/js/sb-admin.min.js vendored Normal file
View File

@ -0,0 +1,7 @@
/*!
* Start Bootstrap - SB Admin v5.1.1 (https://startbootstrap.com/template-overviews/sb-admin)
* Copyright 2013-2019 Start Bootstrap
* Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-sb-admin/blob/master/LICENSE)
*/
!function(l){"use strict";l("#sidebarToggle").on("click",function(o){o.preventDefault(),l("body").toggleClass("sidebar-toggled"),l(".sidebar").toggleClass("toggled")}),l("body.fixed-nav .sidebar").on("mousewheel DOMMouseScroll wheel",function(o){if(768<l(window).width()){var e=o.originalEvent,t=e.wheelDelta||-e.detail;this.scrollTop+=30*(t<0?1:-1),o.preventDefault()}}),l(document).on("scroll",function(){100<l(this).scrollTop()?l(".scroll-to-top").fadeIn():l(".scroll-to-top").fadeOut()}),l(document).on("click","a.scroll-to-top",function(o){var e=l(this);l("html, body").stop().animate({scrollTop:l(e.attr("href")).offset().top},1e3,"easeInOutExpo"),o.preventDefault()})}(jQuery);

View File

@ -0,0 +1,25 @@
// Styling for custom cards
// Custom class for the background icon in card blocks
.card-body-icon {
position: absolute;
z-index: 0;
top: -1.25rem;
right: -1rem;
opacity: 0.4;
font-size: 5rem;
@include rotate;
}
// Override breakpoints for card columns to work well with sidebar layout
.card-columns {
@media (min-width: 576px) {
column-count: 1;
}
@media (min-width: 768px) {
column-count: 2;
}
@media (min-width: 1200px) {
column-count: 2;
}
}

View File

@ -0,0 +1,27 @@
footer.sticky-footer {
display: flex;
position: absolute;
right: 0;
bottom: 0;
width: calc(100% - #{$sidebar-collapsed-width});
height: $sticky-footer-height;
background-color: $gray-200;
.copyright {
line-height: 1;
font-size: 0.8rem;
}
@media (min-width: 768px) {
width: calc(100% - #{$sidebar-base-width});
}
}
body.sidebar-toggled {
footer.sticky-footer {
width: 100%;
}
@media (min-width: 768px) {
footer.sticky-footer {
width: calc(100% - #{$sidebar-collapsed-width});
}
}
}

View File

@ -0,0 +1,44 @@
// Global styling for this template
html {
position: relative;
min-height: 100%;
}
body {
height: 100%;
}
#wrapper {
display: flex;
#content-wrapper {
overflow-x: hidden;
width: 100%;
padding-top: 1rem;
padding-bottom: $sticky-footer-height;
}
}
// Scroll to top button
.scroll-to-top {
position: fixed;
right: 15px;
bottom: 15px;
display: none;
width: 50px;
height: 50px;
text-align: center;
color: $white;
background: fade-out($gray-800, .5);
line-height: 46px;
&:focus,
&:hover {
color: white;
}
&:hover {
background: $gray-800;
}
i {
font-weight: 800;
}
}

View File

@ -0,0 +1,69 @@
:root {
--input-padding-x: 0.75rem;
--input-padding-y: 0.75rem;
}
.card-login {
max-width: 25rem;
}
.card-register {
max-width: 40rem;
}
.form-label-group {
position: relative;
}
.form-label-group > input,
.form-label-group > label {
padding: var(--input-padding-y) var(--input-padding-x);
height: auto;
}
.form-label-group > label {
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
margin-bottom: 0;
/* Override default `<label>` margin */
line-height: 1.5;
color: #495057;
border: 1px solid transparent;
border-radius: 0.25rem;
transition: all 0.1s ease-in-out;
}
.form-label-group input::-webkit-input-placeholder {
color: transparent;
}
.form-label-group input:-ms-input-placeholder {
color: transparent;
}
.form-label-group input::-ms-input-placeholder {
color: transparent;
}
.form-label-group input::-moz-placeholder {
color: transparent;
}
.form-label-group input::placeholder {
color: transparent;
}
.form-label-group input:not(:placeholder-shown) {
padding-top: calc(var(--input-padding-y) + var(--input-padding-y) * (2 / 3));
padding-bottom: calc(var(--input-padding-y) / 3);
}
.form-label-group input:not(:placeholder-shown) ~ label {
padding-top: calc(var(--input-padding-y) / 3);
padding-bottom: calc(var(--input-padding-y) / 3);
font-size: 12px;
color: #777;
}

View File

@ -0,0 +1,33 @@
@mixin rotate {
transform: rotate(15deg);
}
@mixin sidebar-icons {
.nav-item {
&:last-child {
margin-bottom: 1rem;
}
.nav-link {
text-align: center;
padding: 0.75rem 1rem;
width: $sidebar-collapsed-width;
span {
font-size: 0.65rem;
display: block;
}
}
.dropdown-menu {
position: absolute !important;
transform: none !important;
left: calc(#{$sidebar-collapsed-width} + 0.5rem) !important;
margin: 0;
&.dropup {
bottom: 0;
top: auto !important;
}
}
&.dropdown .dropdown-toggle::after {
display: none;
}
}
}

View File

@ -0,0 +1,115 @@
.navbar-nav {
.form-inline .input-group {
width: 100%;
}
.nav-item {
&.active {
.nav-link {
color: $white;
}
}
&.dropdown {
.dropdown-toggle {
&::after {
width: 1rem;
text-align: center;
float: right;
vertical-align: 0;
border: 0;
font-weight: 900;
content: '\f105';
font-family: 'Font Awesome 5 Free';
}
}
&.show {
.dropdown-toggle::after {
content: '\f107';
}
}
&.no-arrow {
.dropdown-toggle::after {
display: none;
}
}
}
.nav-link {
&:focus {
// remove outline for Safari and Firefox
outline: none;
}
.badge {
position: absolute;
margin-left: 0.75rem;
top: 0.3rem;
font-weight: 400;
font-size: 0.5rem;
}
}
}
@media(min-width: 768px) {
.form-inline .input-group {
width: auto;
}
}
}
.sidebar {
width: $sidebar-collapsed-width !important;
background-color: $gray-900;
min-height: calc(100vh - #{$navbar-base-height});
@include sidebar-icons;
.nav-item {
.nav-link {
color: fade-out($white, 0.5);
&:active,
&:focus,
&:hover {
color: fade-out($white, 0.25);
}
}
}
&.toggled {
width: 0 !important;
overflow: hidden;
}
}
@media (min-width: 768px) {
.sidebar {
width: $sidebar-base-width !important;
.nav-item {
.nav-link {
display: block;
width: 100%;
text-align: left;
padding: 1rem;
width: $sidebar-base-width;
span {
font-size: 1rem;
display: inline;
}
}
.dropdown-menu {
position: static !important;
margin: 0 1rem;
// Position fix for Firefox
top: 0;
}
&.dropdown .dropdown-toggle::after {
display: block;
}
}
&.toggled {
overflow: visible;
width: $sidebar-collapsed-width !important;
@include sidebar-icons;
}
}
}

View File

@ -0,0 +1,18 @@
// Additional Text Helper Class
.smaller {
font-size: 0.7rem;
}
// Helper class for the overflow property
.o-hidden {
overflow: hidden !important;
}
// Helper classes for z-index
.z-0 {
z-index: 0;
}
.z-1 {
z-index: 1;
}

View File

@ -0,0 +1,9 @@
// Spacing Variables
// Change below variable if the height of the navbar changes
$navbar-base-height: 56px;
// Change below variable to change the width of the sidenav
$sidebar-base-width: 225px;
// Change below variable to change the width of the sidenav when collapsed
$sidebar-collapsed-width: 90px;
// Change below variable to change the height of the sticky footer
$sticky-footer-height: 80px;

View File

@ -0,0 +1,14 @@
// Import Custom Variables
@import "variables.scss";
// Import Bootstrap
@import "../vendor/bootstrap/scss/bootstrap.scss";
// Import Custom SCSS
@import "mixins.scss";
@import "global.scss";
@import "utilities.scss";
@import "navbar.scss";
@import "cards.scss";
@import "login.scss";
@import "footer.scss";

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,51 @@
//
// Base styles
//
.alert {
position: relative;
padding: $alert-padding-y $alert-padding-x;
margin-bottom: $alert-margin-bottom;
border: $alert-border-width solid transparent;
@include border-radius($alert-border-radius);
}
// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}
// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
}
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissible {
padding-right: $close-font-size + $alert-padding-x * 2;
// Adjust close link position
.close {
position: absolute;
top: 0;
right: 0;
padding: $alert-padding-y $alert-padding-x;
color: inherit;
}
}
// Alternate styles
//
// Generate contextual modifier classes for colorizing the alert.
@each $color, $value in $theme-colors {
.alert-#{$color} {
@include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level));
}
}

View File

@ -0,0 +1,54 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.
.badge {
display: inline-block;
padding: $badge-padding-y $badge-padding-x;
@include font-size($badge-font-size);
font-weight: $badge-font-weight;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
@include border-radius($badge-border-radius);
@include transition($badge-transition);
@at-root a#{&} {
@include hover-focus {
text-decoration: none;
}
}
// Empty badges collapse automatically
&:empty {
display: none;
}
}
// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}
// Pill badges
//
// Make them extra rounded with a modifier to replace v3's badges.
.badge-pill {
padding-right: $badge-pill-padding-x;
padding-left: $badge-pill-padding-x;
@include border-radius($badge-pill-border-radius);
}
// Colors
//
// Contextual variations (linked badges get darker on :hover).
@each $color, $value in $theme-colors {
.badge-#{$color} {
@include badge-variant($value);
}
}

View File

@ -0,0 +1,41 @@
.breadcrumb {
display: flex;
flex-wrap: wrap;
padding: $breadcrumb-padding-y $breadcrumb-padding-x;
margin-bottom: $breadcrumb-margin-bottom;
list-style: none;
background-color: $breadcrumb-bg;
@include border-radius($breadcrumb-border-radius);
}
.breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item {
padding-left: $breadcrumb-item-padding;
&::before {
display: inline-block; // Suppress underlining of the separator in modern browsers
padding-right: $breadcrumb-item-padding;
color: $breadcrumb-divider-color;
content: $breadcrumb-divider;
}
}
// IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built
// without `<ul>`s. The `::before` pseudo-element generates an element
// *within* the .breadcrumb-item and thereby inherits the `text-decoration`.
//
// To trick IE into suppressing the underline, we give the pseudo-element an
// underline and then immediately remove it.
+ .breadcrumb-item:hover::before {
text-decoration: underline;
}
// stylelint-disable-next-line no-duplicate-selectors
+ .breadcrumb-item:hover::before {
text-decoration: none;
}
&.active {
color: $breadcrumb-active-color;
}
}

View File

@ -0,0 +1,163 @@
// stylelint-disable selector-no-qualifying-type
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above
> .btn {
position: relative;
flex: 1 1 auto;
// Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly
@include hover {
z-index: 1;
}
&:focus,
&:active,
&.active {
z-index: 1;
}
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.input-group {
width: auto;
}
}
.btn-group {
// Prevent double borders when buttons are next to each other
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-left: -$btn-border-width;
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-right-radius(0);
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn {
@include border-left-radius(0);
}
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; }
//
// Split button dropdowns
//
.dropdown-toggle-split {
padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75;
&::after,
.dropup &::after,
.dropright &::after {
margin-left: 0;
}
.dropleft &::before {
margin-right: 0;
}
}
.btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75;
}
.btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75;
}
// The clickable button for toggling the menu
// Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle {
@include box-shadow($btn-active-box-shadow);
// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link {
@include box-shadow(none);
}
}
//
// Vertical button groups
//
.btn-group-vertical {
flex-direction: column;
align-items: flex-start;
justify-content: center;
> .btn,
> .btn-group {
width: 100%;
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-top: -$btn-border-width;
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-bottom-radius(0);
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn {
@include border-top-radius(0);
}
}
// Checkbox and radio options
//
// In order to support the browser's form validation feedback, powered by the
// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
// `display: none;` or `visibility: hidden;` as that also hides the popover.
// Simply visually hiding the inputs via `opacity` would leave them clickable in
// certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from.
//
// See https://github.com/twbs/bootstrap/pull/12794 and
// https://github.com/twbs/bootstrap/pull/14559 for more information.
.btn-group-toggle {
> .btn,
> .btn-group > .btn {
margin-bottom: 0; // Override default `<label>` value
input[type="radio"],
input[type="checkbox"] {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
}
}
}

View File

@ -0,0 +1,137 @@
// stylelint-disable selector-no-qualifying-type
//
// Base styles
//
.btn {
display: inline-block;
font-family: $btn-font-family;
font-weight: $btn-font-weight;
color: $body-color;
text-align: center;
vertical-align: middle;
user-select: none;
background-color: transparent;
border: $btn-border-width solid transparent;
@include button-size($btn-padding-y, $btn-padding-x, $btn-font-size, $btn-line-height, $btn-border-radius);
@include transition($btn-transition);
@include hover {
color: $body-color;
text-decoration: none;
}
&:focus,
&.focus {
outline: 0;
box-shadow: $btn-focus-box-shadow;
}
// Disabled comes first so active can properly restyle
&.disabled,
&:disabled {
opacity: $btn-disabled-opacity;
@include box-shadow(none);
}
&:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active {
@include box-shadow($btn-active-box-shadow);
&:focus {
@include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
}
}
}
// Future-proof disabling of clicks on `<a>` elements
a.btn.disabled,
fieldset:disabled a.btn {
pointer-events: none;
}
//
// Alternate buttons
//
@each $color, $value in $theme-colors {
.btn-#{$color} {
@include button-variant($value, $value);
}
}
@each $color, $value in $theme-colors {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link {
font-weight: $font-weight-normal;
color: $link-color;
text-decoration: $link-decoration;
@include hover {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
}
&:focus,
&.focus {
text-decoration: $link-hover-decoration;
box-shadow: none;
}
&:disabled,
&.disabled {
color: $btn-link-disabled-color;
pointer-events: none;
}
// No need for an active state here
}
//
// Button Sizes
//
.btn-lg {
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-line-height-lg, $btn-border-radius-lg);
}
.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-line-height-sm, $btn-border-radius-sm);
}
//
// Block button
//
.btn-block {
display: block;
width: 100%;
// Vertically space out multiple block buttons
+ .btn-block {
margin-top: $btn-block-spacing-y;
}
}
// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"] {
&.btn-block {
width: 100%;
}
}

View File

@ -0,0 +1,289 @@
//
// Base styles
//
.card {
position: relative;
display: flex;
flex-direction: column;
min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
word-wrap: break-word;
background-color: $card-bg;
background-clip: border-box;
border: $card-border-width solid $card-border-color;
@include border-radius($card-border-radius);
> hr {
margin-right: 0;
margin-left: 0;
}
> .list-group:first-child {
.list-group-item:first-child {
@include border-top-radius($card-border-radius);
}
}
> .list-group:last-child {
.list-group-item:last-child {
@include border-bottom-radius($card-border-radius);
}
}
}
.card-body {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto;
padding: $card-spacer-x;
color: $card-color;
}
.card-title {
margin-bottom: $card-spacer-y;
}
.card-subtitle {
margin-top: -$card-spacer-y / 2;
margin-bottom: 0;
}
.card-text:last-child {
margin-bottom: 0;
}
.card-link {
@include hover {
text-decoration: none;
}
+ .card-link {
margin-left: $card-spacer-x;
}
}
//
// Optional textual caps
//
.card-header {
padding: $card-spacer-y $card-spacer-x;
margin-bottom: 0; // Removes the default margin-bottom of <hN>
color: $card-cap-color;
background-color: $card-cap-bg;
border-bottom: $card-border-width solid $card-border-color;
&:first-child {
@include border-radius($card-inner-border-radius $card-inner-border-radius 0 0);
}
+ .list-group {
.list-group-item:first-child {
border-top: 0;
}
}
}
.card-footer {
padding: $card-spacer-y $card-spacer-x;
background-color: $card-cap-bg;
border-top: $card-border-width solid $card-border-color;
&:last-child {
@include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius);
}
}
//
// Header navs
//
.card-header-tabs {
margin-right: -$card-spacer-x / 2;
margin-bottom: -$card-spacer-y;
margin-left: -$card-spacer-x / 2;
border-bottom: 0;
}
.card-header-pills {
margin-right: -$card-spacer-x / 2;
margin-left: -$card-spacer-x / 2;
}
// Card image
.card-img-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: $card-img-overlay-padding;
}
.card-img {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
@include border-radius($card-inner-border-radius);
}
// Card image caps
.card-img-top {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
@include border-top-radius($card-inner-border-radius);
}
.card-img-bottom {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
@include border-bottom-radius($card-inner-border-radius);
}
// Card deck
.card-deck {
display: flex;
flex-direction: column;
.card {
margin-bottom: $card-deck-margin;
}
@include media-breakpoint-up(sm) {
flex-flow: row wrap;
margin-right: -$card-deck-margin;
margin-left: -$card-deck-margin;
.card {
display: flex;
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%;
flex-direction: column;
margin-right: $card-deck-margin;
margin-bottom: 0; // Override the default
margin-left: $card-deck-margin;
}
}
}
//
// Card groups
//
.card-group {
display: flex;
flex-direction: column;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
margin-bottom: $card-group-margin;
}
@include media-breakpoint-up(sm) {
flex-flow: row wrap;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%;
margin-bottom: 0;
+ .card {
margin-left: 0;
border-left: 0;
}
// Handle rounded corners
@if $enable-rounded {
&:not(:last-child) {
@include border-right-radius(0);
.card-img-top,
.card-header {
// stylelint-disable-next-line property-blacklist
border-top-right-radius: 0;
}
.card-img-bottom,
.card-footer {
// stylelint-disable-next-line property-blacklist
border-bottom-right-radius: 0;
}
}
&:not(:first-child) {
@include border-left-radius(0);
.card-img-top,
.card-header {
// stylelint-disable-next-line property-blacklist
border-top-left-radius: 0;
}
.card-img-bottom,
.card-footer {
// stylelint-disable-next-line property-blacklist
border-bottom-left-radius: 0;
}
}
}
}
}
}
//
// Columns
//
.card-columns {
.card {
margin-bottom: $card-columns-margin;
}
@include media-breakpoint-up(sm) {
column-count: $card-columns-count;
column-gap: $card-columns-gap;
orphans: 1;
widows: 1;
.card {
display: inline-block; // Don't let them vertically span multiple columns
width: 100%; // Don't let their width change
}
}
}
//
// Accordion
//
.accordion {
> .card {
overflow: hidden;
&:not(:first-of-type) {
.card-header:first-child {
@include border-radius(0);
}
&:not(:last-of-type) {
border-bottom: 0;
@include border-radius(0);
}
}
&:first-of-type {
border-bottom: 0;
@include border-bottom-radius(0);
}
&:last-of-type {
@include border-top-radius(0);
}
.card-header {
margin-bottom: -$card-border-width;
}
}
}

Some files were not shown because too many files have changed in this diff Show More