Add widget framework, add full 2fa support, add password changing,

add blacklist of common passwords
V2_Rewrite
Skylar Ittner 7 years ago
parent af3ddcbc90
commit 549564540b

@ -0,0 +1,57 @@
<?php
/**
* Make things happen when buttons are pressed and forms submitted.
*/
require_once __DIR__ . "/required.php";
dieifnotloggedin();
require_once __DIR__ . "/lib/worst_passwords.php";
function returnToSender($msg, $arg = "") {
global $VARS;
if ($arg == "") {
header("Location: home.php?page=" . urlencode($VARS['source']) . "&msg=" . $msg);
} else {
header("Location: home.php?page=" . urlencode($VARS['source']) . "&msg=$msg&arg=$arg");
}
die();
}
switch ($VARS['action']) {
case "signout":
session_destroy();
header('Location: index.php');
die("Logged out.");
case "chpasswd":
$oldmatch = comparePassword($VARS['oldpass'], $database->select('accounts', 'password', ['uid' => $_SESSION['uid']])[0]);
if ($oldmatch) {
if ($VARS['newpass'] == $VARS['conpass']) {
$passrank = checkWorst500List($VARS['newpass']);
if ($passrank !== FALSE) {
returnToSender("password_500", $passrank);
}
if (strlen($VARS['newpass']) < MIN_PASSWORD_LENGTH) {
returnToSender("weak_password");
}
$database->update('accounts', ['password' => encryptPassword($VARS['newpass'])], ['uid' => $_SESSION['uid']]);
returnToSender("password_updated");
} else {
returnToSender("new_password_mismatch");
}
} else {
returnToSender("old_password_mismatch");
}
break;
case "add2fa":
if (is_empty($VARS['secret'])) {
returnToSender("invalid_parameters");
}
$database->update('accounts', ['authsecret' => $VARS['secret']], ['uid' => $_SESSION['uid']]);
returnToSender("2fa_enabled");
case "rm2fa":
$database->update('accounts', ['authsecret' => ""], ['uid' => $_SESSION['uid']]);
returnToSender("2fa_removed");
break;
}

@ -0,0 +1,17 @@
<?php
dieifnotloggedin();
// extra login utils
require_once __DIR__ . "/../lib/login.php";
$APPS["setup_2fa"]["title"] = lang("setup 2fa", false);
$APPS["setup_2fa"]["icon"] = "lock";
if (userHasTOTP($_SESSION['username'])) {
$APPS["setup_2fa"]["content"] = '<a href="action.php?action=rm2fa&source=security" class="btn btn-warning">'
. lang("remove 2fa", false) . '</a>';
} else {
$APPS["setup_2fa"]["content"] = '<div class="alert alert-info"><i class="fa fa-info-circle"></i> ' . lang("2fa explained", false) . '</div>'
. '<button class="btn btn-success">'
. lang("enable 2fa", false) . '</button>';
}

@ -0,0 +1,9 @@
<?php
dieifnotloggedin();
$APPS["404_error"]["title"] = lang("404 error", false);
$APPS["404_error"]["icon"] = "times";
$APPS["404_error"]["type"] = "warning";
$APPS["404_error"]["content"] = "<h4>" . lang("page not found", false) . "</h4>";
?>

@ -0,0 +1,17 @@
<?php
dieifnotloggedin();
$APPS["change_password"]["title"] = "Change Password";
$APPS["change_password"]["icon"] = "key";
$APPS["change_password"]["content"] = <<<CONTENTEND
<form action="action.php" method="POST">
<input type="password" class="form-control" name="oldpass" placeholder="Old password" />
<input type="password" class="form-control" name="newpass" placeholder="New password" />
<input type="password" class="form-control" name="conpass" placeholder="New password (again)" />
<input type="hidden" name="action" value="chpasswd" />
<input type="hidden" name="source" value="security" />
<br />
<button type="submit" class="btn btn-success btn-sm btn-block">Change Password</button>
</form>
CONTENTEND;

@ -0,0 +1,20 @@
<?php
dieifnotloggedin();
$APPS["sample_app"]["title"] = "Sample App";
$APPS["sample_app"]["icon"] = "rocket";
$APPS["sample_app"]["content"] = <<<'CONTENTEND'
<div class="list-group">
<div class="list-group-item">
Item 1
</div>
<div class="list-group-item">
Item 2
</div>
<div class="list-group-item">
Item 3
</div>
</div>
CONTENTEND;
?>

@ -0,0 +1,43 @@
<?php
dieifnotloggedin();
use OTPHP\Factory;
use Endroid\QrCode\QrCode;
// extra login utils
require_once __DIR__ . "/../lib/login.php";
$APPS["setup_2fa"]["title"] = lang("setup 2fa", false);
$APPS["setup_2fa"]["icon"] = "lock";
if (userHasTOTP($_SESSION['username'])) {
$APPS["setup_2fa"]["content"] = '<div class="alert alert-info"><i class="fa fa-info-circle"></i> ' . lang("2fa active", false) . '</div>'
. '<a href="action.php?action=rm2fa&source=security" class="btn btn-warning btn-sm btn-block">'
. lang("remove 2fa", false) . '</a>';
} else if ($_GET['2fa'] == "generate") {
$codeuri = newTOTP($_SESSION['username']);
$qrCode = new QrCode($codeuri);
$qrCode->setSize(200);
$qrCode->setErrorCorrection("H");
$qrcode = $qrCode->getDataUri();
$totp = Factory::loadFromProvisioningUri($codeuri);
$codesecret = $totp->getSecret();
$chunk_secret = trim(chunk_split($codesecret, 8, ' '));
$APPS["setup_2fa"]["content"] = '<div class="alert alert-info"><i class="fa fa-info-circle"></i> ' . lang("scan 2fa qrcode", false) . '</div>' . <<<END
<img src="$qrcode" class="img-responsive qrcode" />
<div class="well well-sm" style="text-align: center; font-size: 110%; font-family: monospace;">$chunk_secret</div>
<form action="action.php" method="POST">
<input type="hidden" name="action" value="add2fa" />
<input type="hidden" name="source" value="security" />
<input type="hidden" name="secret" value="$codesecret" />
<button type="submit" class="btn btn-success btn-sm btn-block">
END
. lang("confirm 2fa", false) . <<<END
</button>
</form>
END;
} else {
$APPS["setup_2fa"]["content"] = '<div class="alert alert-info"><i class="fa fa-info-circle"></i> ' . lang("2fa explained", false) . '</div>'
. '<a class="btn btn-success btn-sm btn-block" href="home.php?page=security&2fa=generate">'
. lang("enable 2fa", false) . '</a>';
}

@ -1,6 +1,176 @@
<?php
require_once __DIR__ . "/required.php";
dieifnotloggedin();
if ($_SESSION['loggedin'] != true) {
header('Location: index.php');
die("Session expired. Log in again to continue.");
}
require_once __DIR__ . "/pages.php";
$pageid = "home";
if (!is_empty($_GET['page'])) {
if (array_key_exists($_GET['page'], PAGES)) {
$pageid = $_GET['page'];
} else {
$pageid = "404";
}
}
?>
Home
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" contgreent="width=device-width, initial-scale=1">
<title><?php echo SITE_TITLE; ?></title>
<link href="static/css/bootstrap.min.css" rel="stylesheet">
<link href="static/css/font-awesome.min.css" rel="stylesheet">
<link href="static/css/app.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4">
<img class="img-responsive banner-image" src="static/img/banner.png" />
</div>
</div>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<?php
if (PAGES[$pageid]['title'] == "{DEFAULT}") {
?>
<span class="navbar-brand">
<?php
lang2("welcome user", ["user" => $_SESSION['realname']]);
?>
</span>
<?php
} else {
?>
<a class="navbar-brand" href="home.php?page=home">
<?php
// add breadcrumb thing
lang("home");
echo " <i class=\"fa fa-caret-right\"></i> ";
lang(PAGES[$pageid]['title']);
?>
</a>
<?php
}
?>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-gears"></i> <?php lang("settings"); ?> <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="home.php?page=security"><i class="fa fa-lock"></i> <?php lang("account security"); ?></a></li>
<li class="divider"></li>
<li><a href="action.php?action=signout"><?php lang("sign out"); ?></a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<?php
// Alert messages
if (!is_empty($_GET['msg']) && array_key_exists($_GET['msg'], MESSAGES)) {
// optional string generation argument
if (is_empty($_GET['arg'])) {
$alertmsg = lang(MESSAGES[$_GET['msg']]['string'], false);
} else {
$alertmsg = lang2(MESSAGES[$_GET['msg']]['string'], ["arg" => $_GET['arg']], false);
}
$alerttype = MESSAGES[$_GET['msg']]['type'];
$alerticon = "square-o";
switch (MESSAGES[$_GET['msg']]['type']) {
case "danger":
$alerticon = "times";
break;
case "warning":
$alerticon = "exclamation-triangle";
break;
case "info":
$alerticon = "info-circle";
break;
case "success":
$alerticon = "check";
break;
}
echo <<<END
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4">
<div class="alert alert-dismissible alert-$alerttype">
<button type="button" class="close">&times;</button>
<i class="fa fa-$alerticon"></i> $alertmsg
</div>
</div>
</div>
END;
}
?>
<div class="row">
<?php
// Center the widgets horizontally on the screen
$appcount = count(APPS[$pageid]);
if ($appcount == 1) {
?>
<div class="hidden-xs col-sm-3 col-md-4 col-lg-4">
<!-- Placeholder column for nice center-align -->
</div>
<?php
} else if ($appcount == 2) {
?>
<div class="hidden-xs hidden-sm col-md-2 col-lg-2">
<!-- Placeholder column for nice center-align -->
</div>
<?php
}
foreach (APPS[$pageid] as $app) {
if (file_exists(__DIR__ . "/apps/" . $app . ".php")) {
include_once __DIR__ . "/apps/" . $app . ".php";
$apptitle = $APPS[$app]['title'];
$appicon = (is_empty($APPS[$app]['icon']) ? "" : "fa fa-" . $APPS[$app]['icon']);
$apptype = (is_empty($APPS[$app]['type']) ? "default" : $APPS[$app]['type']);
$appcontent = $APPS[$app]['content'];
echo <<<END
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<div class="panel panel-$apptype">
<div class="panel-heading">
<h3 class="panel-title"><i class="$appicon"></i> $apptitle </h3>
</div>
<div class="panel-body">
$appcontent
</div>
</div>
</div>
END;
}
}
?>
</div>
<div class="footer">
<?php echo LICENSE_TEXT; ?><br />
Copyright &copy; <?php echo date('Y'); ?> <?php echo COPYRIGHT_NAME; ?>
</div>
</div>
<script src="static/js/jquery-3.2.1.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
<script src="static/js/app.js"></script>
</body>
</html>

@ -106,6 +106,10 @@ if ($VARS['progress'] == "1") {
</div>
</div>
</div>
<div class="footer">
<?php echo LICENSE_TEXT; ?><br />
Copyright &copy; <?php echo date('Y'); ?> <?php echo COPYRIGHT_NAME; ?>
</div>
</div>
<script src="static/js/jquery-3.2.1.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>

@ -11,5 +11,29 @@ define("STRINGS", [
"login incorrect" => "Login incorrect.",
"account locked" => "This account has been disabled. Contact technical support.",
"password expired" => "You must change your password before continuing.",
"account terminated" => "Account terminated. Access denied."
"account terminated" => "Account terminated. Access denied.",
"password on 500 list" => "The given password is ranked number {arg} out of the 500 most common passwords. Try a different one.",
"welcome user" => "Welcome, {user}!",
"change password" => "Change password",
"security options" => "Security options",
"account security" => "Account security",
"sign out" => "Sign out",
"settings" => "Settings",
"404 error" => "404 Error",
"page not found" => "Page not found.",
"current password incorrect" => "The current password is incorrect. Try again.",
"new password mismatch" => "The new passwords did not match. Try again.",
"weak password" => "Password does not meet requirements.",
"password updated" => "Password updated successfully.",
"setup 2fa" => "Setup 2-factor authentication",
"2fa removed" => "2-factor authentication disabled.",
"2fa enabled" => "2-factor authentication activated.",
"remove 2fa" => "Disable 2-factor authentication",
"2fa explained" => "2-factor authentication adds more security to your account. You'll need an app such as Google Authenticator on your smartphone. When you have the app installed, you can enable 2-factor authentication by clicking the button below and scanning a QR code with the app. Whenever you sign in in the future, you'll need to input a six-digit code from your phone into the login page when prompted. You can disable 2-factor authentication from this page if you change your mind.",
"2fa active" => "2-factor authentication is active on your account. To remove 2fa, reset your authentication secret, or change to a new security device, click the button below.",
"enable 2fa" => "Enable 2-factor authentication",
"scan 2fa qrcode" => "Scan the QR Code with the authenticator app, or enter the secret key manually.",
"confirm 2fa" => "Finish setup",
"invalid parameters" => "Invalid request parameters.",
"home" => "Home",
]);

@ -0,0 +1,36 @@
<?php
define("MESSAGES", [
"old_password_mismatch" => [
"string" => "current password incorrect",
"type" => "danger"
],
"new_password_mismatch" => [
"string" => "new password mismatch",
"type" => "danger"
],
"weak_password" => [
"string" => "weak password",
"type" => "danger"
],
"password_updated" => [
"string" => "password updated",
"type" => "success"
],
"2fa_removed" => [
"string" => "2fa removed",
"type" => "success"
],
"2fa_enabled" => [
"string" => "2fa enabled",
"type" => "success"
],
"invalid_parameters" => [
"string" => "invalid parameters",
"type" => "danger"
],
"password_500" => [
"string" => "password on 500 list",
"type" => "danger"
]
]);

@ -43,7 +43,7 @@ function userHasTOTP($username) {
}
/**
* Generate and store a TOTP secret for the given user.
* Generate a TOTP secret for the given user.
* @param string $username
* @return string OTP provisioning URI (for generating a QR code)
*/
@ -54,10 +54,20 @@ function newTOTP($username) {
$userdata = $database->select('accounts', ['email', 'authsecret'], ['username' => $username])[0];
$totp = new TOTP($userdata['email'], $encoded_secret);
$totp->setIssuer(SYSTEM_NAME);
$database->update('accounts', ['authsecret' => $encoded_secret], ['username' => $username]);
return $totp->getProvisioningUri();
}
/**
* Save a TOTP secret for the user.
* @global $database $database
* @param string $username
* @param string $secret
*/
function saveTOTP($username, $secret) {
global $database;
$database->update('accounts', ['authsecret' => $secret], ['username' => $username]);
}
/**
* Verify a TOTP multiauth code
* @global $database
@ -72,6 +82,5 @@ function verifyTOTP($username, $code) {
return false;
}
$totp = new TOTP(null, $userdata['authsecret']);
echo $userdata['authsecret'] . ", " . $totp->now() . ", " . $code;
return $totp->verify($code);
}

@ -0,0 +1,522 @@
<?php
/*
* 500 most common passwords, to be used in stopping idiots from having really bad passwords.
* Source: https://github.com/danielmiessler/SecLists/blob/master/Passwords/500-worst-passwords.txt
*/
/**
* Checks a given password against the list of the 500 most common passwords.
* @param string $search the password to check
* @return false if not found, the password ranking if found
*/
function checkWorst500List($search) {
$worst_password_list = [
"123456",
"password",
"12345678",
"1234",
"pussy",
"12345",
"dragon",
"qwerty",
"696969",
"mustang",
"letmein",
"baseball",
"master",
"michael",
"football",
"shadow",
"monkey",
"abc123",
"pass",
"fuckme",
"6969",
"jordan",
"harley",
"ranger",
"iwantu",
"jennifer",
"hunter",
"fuck",
"2000",
"test",
"batman",
"trustno1",
"thomas",
"tigger",
"robert",
"access",
"love",
"buster",
"1234567",
"soccer",
"hockey",
"killer",
"george",
"sexy",
"andrew",
"charlie",
"superman",
"asshole",
"fuckyou",
"dallas",
"jessica",
"panties",
"pepper",
"1111",
"austin",
"william",
"daniel",
"golfer",
"summer",
"heather",
"hammer",
"yankees",
"joshua",
"maggie",
"biteme",
"enter",
"ashley",
"thunder",
"cowboy",
"silver",
"richard",
"fucker",
"orange",
"merlin",
"michelle",
"corvette",
"bigdog",
"cheese",
"matthew",
"121212",
"patrick",
"martin",
"freedom",
"ginger",
"blowjob",
"nicole",
"sparky",
"yellow",
"camaro",
"secret",
"dick",
"falcon",
"taylor",
"111111",
"131313",
"123123",
"bitch",
"hello",
"scooter",
"please",
"porsche",
"guitar",
"chelsea",
"black",
"diamond",
"nascar",
"jackson",
"cameron",
"654321",
"computer",
"amanda",
"wizard",
"xxxxxxxx",
"money",
"phoenix",
"mickey",
"bailey",
"knight",
"iceman",
"tigers",
"purple",
"andrea",
"horny",
"dakota",
"aaaaaa",
"player",
"sunshine",
"morgan",
"starwars",
"boomer",
"cowboys",
"edward",
"charles",
"girls",
"booboo",
"coffee",
"xxxxxx",
"bulldog",
"ncc1701",
"rabbit",
"peanut",
"john",
"johnny",
"gandalf",
"spanky",
"winter",
"brandy",
"compaq",
"carlos",
"tennis",
"james",
"mike",
"brandon",
"fender",
"anthony",
"blowme",
"ferrari",
"cookie",
"chicken",
"maverick",
"chicago",
"joseph",
"diablo",
"sexsex",
"hardcore",
"666666",
"willie",
"welcome",
"chris",
"panther",
"yamaha",
"justin",
"banana",
"driver",
"marine",
"angels",
"fishing",
"david",
"maddog",
"hooters",
"wilson",
"butthead",
"dennis",
"fucking",
"captain",
"bigdick",
"chester",
"smokey",
"xavier",
"steven",
"viking",
"snoopy",
"blue",
"eagles",
"winner",
"samantha",
"house",
"miller",
"flower",
"jack",
"firebird",
"butter",
"united",
"turtle",
"steelers",
"tiffany",
"zxcvbn",
"tomcat",
"golf",
"bond007",
"bear",
"tiger",
"doctor",
"gateway",
"gators",
"angel",
"junior",
"thx1138",
"porno",
"badboy",
"debbie",
"spider",
"melissa",
"booger",
"1212",
"flyers",
"fish",
"porn",
"matrix",
"teens",
"scooby",
"jason",
"walter",
"cumshot",
"boston",
"braves",
"yankee",
"lover",
"barney",
"victor",
"tucker",
"princess",
"mercedes",
"5150",
"doggie",
"zzzzzz",
"gunner",
"horney",
"bubba",
"2112",
"fred",
"johnson",
"xxxxx",
"tits",
"member",
"boobs",
"donald",
"bigdaddy",
"bronco",
"penis",
"voyager",
"rangers",
"birdie",
"trouble",
"white",
"topgun",
"bigtits",
"bitches",
"green",
"super",
"qazwsx",
"magic",
"lakers",
"rachel",
"slayer",
"scott",
"2222",
"asdf",
"video",
"london",
"7777",
"marlboro",
"srinivas",
"internet",
"action",
"carter",
"jasper",
"monster",
"teresa",
"jeremy",
"11111111",
"bill",
"crystal",
"peter",
"pussies",
"cock",
"beer",
"rocket",
"theman",
"oliver",
"prince",
"beach",
"amateur",
"7777777",
"muffin",
"redsox",
"star",
"testing",
"shannon",
"murphy",
"frank",
"hannah",
"dave",
"eagle1",
"11111",
"mother",
"nathan",
"raiders",
"steve",
"forever",
"angela",
"viper",
"ou812",
"jake",
"lovers",
"suckit",
"gregory",
"buddy",
"whatever",
"young",
"nicholas",
"lucky",
"helpme",
"jackie",
"monica",
"midnight",
"college",
"baby",
"cunt",
"brian",
"mark",
"startrek",
"sierra",
"leather",
"232323",
"4444",
"beavis",
"bigcock",
"happy",
"sophie",
"ladies",
"naughty",
"giants",
"booty",
"blonde",
"fucked",
"golden",
"0",
"fire",
"sandra",
"pookie",
"packers",
"einstein",
"dolphins",
"chevy",
"winston",
"warrior",
"sammy",
"slut",
"8675309",
"zxcvbnm",
"nipples",
"power",
"victoria",
"asdfgh",
"vagina",
"toyota",
"travis",
"hotdog",
"paris",
"rock",
"xxxx",
"extreme",
"redskins",
"erotic",
"dirty",
"ford",
"freddy",
"arsenal",
"access14",
"wolf",
"nipple",
"iloveyou",
"alex",
"florida",
"eric",
"legend",
"movie",
"success",
"rosebud",
"jaguar",
"great",
"cool",
"cooper",
"1313",
"scorpio",
"mountain",
"madison",
"987654",
"brazil",
"lauren",
"japan",
"naked",
"squirt",
"stars",
"apple",
"alexis",
"aaaa",
"bonnie",
"peaches",
"jasmine",
"kevin",
"matt",
"qwertyui",
"danielle",
"beaver",
"4321",
"4128",
"runner",
"swimming",
"dolphin",
"gordon",
"casper",
"stupid",
"shit",
"saturn",
"gemini",
"apples",
"august",
"3333",
"canada",
"blazer",
"cumming",
"hunting",
"kitty",
"rainbow",
"112233",
"arthur",
"cream",
"calvin",
"shaved",
"surfer",
"samson",
"kelly",
"paul",
"mine",
"king",
"racing",
"5555",
"eagle",
"hentai",
"newyork",
"little",
"redwings",
"smith",
"sticky",
"cocacola",
"animal",
"broncos",
"private",
"skippy",
"marvin",
"blondes",
"enjoy",
"girl",
"apollo",
"parker",
"qwert",
"time",
"sydney",
"women",
"voodoo",
"magnum",
"juice",
"abgrtyu",
"777777",
"dreams",
"maxwell",
"music",
"rush2112",
"russia",
"scorpion",
"rebecca",
"tester",
"mistress",
"phantom",
"billy",
"6666",
"albert"
];
$index = array_search($search, $worst_password_list);
if ($index === FALSE) {
return false;
} else {
return $index + 1;
}
}

@ -0,0 +1,28 @@
<?php
// List of pages and metadata
define("PAGES", [
"home" => [
"title" => "{DEFAULT}"
],
"security" => [
"title" => "security options"
],
"404" => [
"title" => "404 error"
]
]);
// Which apps to load on a given page
define("APPS", [
"home" => [
"sample_app"
],
"security" => [
"change_password",
"setup_2fa"
],
"404" => [
"404_error"
]
]);

@ -13,6 +13,8 @@ require __DIR__ . '/vendor/autoload.php';
// Settings file
require __DIR__ . '/settings.php';
require __DIR__ . '/lang/messages.php';
require __DIR__ . '/lang/' . LANGUAGE . ".php";
function sendError($error) {
@ -67,13 +69,44 @@ function is_empty($str) {
return (is_null($str) || !isset($str) || $str == '');
}
/**
* I18N string getter. If the key doesn't exist, outputs the key itself.
* @param string $key I18N string key
* @param boolean $echo whether to echo the result or return it (default echo)
*/
function lang($key, $echo = true) {
if (array_key_exists($key, STRINGS)) {
$str = STRINGS[$key];
} else {
$str = $key;
}
if ($echo) {
echo $str;
} else {
return $str;
}
}
/**
* I18N string getter (with builder). If the key doesn't exist, outputs the key itself.
* @param string $key I18N string key
* @param array $replace key-value array of replacements.
* If the string value is "hello {abc}" and you give ["abc" => "123"], the
* result will be "hello 123".
* @param boolean $echo whether to echo the result or return it (default echo)
*/
function lang2($key, $replace, $echo = true) {
if (array_key_exists($key, STRINGS)) {
$str = STRINGS[$key];
} else {
$str = $key;
}
foreach ($replace as $find => $repl) {
$str = str_replace("{" . $find . "}", $repl, $str);
}
if ($echo) {
echo $str;
} else {

@ -21,8 +21,6 @@ define("SITE_TITLE", "Netsyms Business Apps :: Single Sign On");
// Used to identify the system in OTP and other places
define("SYSTEM_NAME", "Netsyms SSO Demo");
define("COPYRIGHT_NAME", "Netsyms Technologies");
// For supported values, see http://php.net/manual/en/timezones.php
define("TIMEZONE", "America/Denver");
@ -32,5 +30,25 @@ define('URL', 'http://localhost:8000/');
// See lang folder for language options
define('LANGUAGE', "en_us");
// Minimum length for new passwords
// The system checks new passwords against the 500 worst passwords and rejects
// any matches.
// If you want to have additional password requirements, go edit action.php.
// However, all that does is encourage people to use the infamous
// "post-it password manager". See also https://xkcd.com/936/ and
// http://stackoverflow.com/a/34166252/2534036 for reasons why forcing passwords
// like CaPs45$% is not actually a great idea.
// Encourage users to use 2-factor auth whenever possible.
define("MIN_PASSWORD_LENGTH", 8);
// Maximum number of rows to get in a query.
define("QUERY_LIMIT", 1000);
define("QUERY_LIMIT", 1000);
///////////////////////////////////////////////////////////////////////////////////////////////
// /!\ Warning: Changing these values may violate the terms of your license agreement! /!\ //
///////////////////////////////////////////////////////////////////////////////////////////////
define("LICENSE_TEXT", "<b>Unlicensed Demo: For Trial Use Only</b>");
define("COPYRIGHT_NAME", "Netsyms Technologies");
/////////////////////////////////////////////////////////////////////////////////////////////

@ -1,3 +1,24 @@
.banner-image {
margin: 2em 0em;
max-height: 100px;
margin: 2em auto;
}
.navbar-brand {
font-size: 110%;
}
.footer {
margin-top: 10em;
text-align: center;
}
.qrcode {
width: 100%;
max-width: 300px;
margin: 0 auto;
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast;/* Webkit (non-standard naming) */
image-rendering: crisp-edges;
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
}

@ -0,0 +1,7 @@
$(document).ready(function () {
/* Fade out alerts */
$(".alert .close").click(function (e) {
$(this).parent().fadeOut('slow');
});
});
Loading…
Cancel
Save