Create from template@0c85643847
當前提交
b80d8ffa9b
@ -0,0 +1,4 @@
|
||||
vendor
|
||||
settings.php
|
||||
nbproject/private
|
||||
*.sync-conflict*
|
@ -0,0 +1,36 @@
|
||||
Copyright (C) 2017 Netsyms Technologies. All rights reserved.
|
||||
|
||||
**Definitions:**
|
||||
* "the code", "the software", or "code" refers to the application (or any portion
|
||||
thereof, in any form) this license is included with, excluding third-party libraries.
|
||||
* "any form" means source code, binaries, or any other representation of the code.
|
||||
* "explicit written permission" refers to a written, signed, non-transferable
|
||||
statement from Netsyms Technologies granting you additional rights to the code.
|
||||
|
||||
**You are allowed to:**
|
||||
* use the code for personal and non-commercial purposes.
|
||||
* modify the code for personal and non-commercial purposes.
|
||||
|
||||
**You are NOT allowed to:**
|
||||
* redistribute the code in any form.
|
||||
* sell the code in any form.
|
||||
* use the code for any projects you redistribute or sell, unless you have
|
||||
explicit written permission.
|
||||
* use the code for any projects that are not both personal and non-commercial.
|
||||
* use the code for commercial, business, or non-profit purposes without
|
||||
explicit written permission.
|
||||
* do anything else not permitted in this license.
|
||||
|
||||
**You must:**
|
||||
* retain any and all copyright notices in the code.
|
||||
* retain any and all license notices in the code.
|
||||
* ask for clarification from Netsyms Technologies if any portion of this license
|
||||
is unclear or ambiguous.
|
||||
|
||||
**Disclaimer:**
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,4 @@
|
||||
QwikClock
|
||||
=========
|
||||
|
||||
QwikClock is an employee time tracking app.
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Make things happen when buttons are pressed and forms submitted.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . "/required.php";
|
||||
|
||||
dieifnotloggedin();
|
||||
|
||||
/**
|
||||
* Redirects back to the page ID in $_POST/$_GET['source'] with the given message ID.
|
||||
* The message will be displayed by the app.
|
||||
* @param string $msg message ID (see lang/messages.php)
|
||||
* @param string $arg If set, replaces "{arg}" in the message string when displayed to the user.
|
||||
*/
|
||||
function returnToSender($msg, $arg = "") {
|
||||
global $VARS;
|
||||
if ($arg == "") {
|
||||
header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=" . $msg);
|
||||
} else {
|
||||
header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=$msg&arg=$arg");
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
switch ($VARS['action']) {
|
||||
case "signout":
|
||||
session_destroy();
|
||||
header('Location: index.php');
|
||||
die("Logged out.");
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Simple JSON API to allow other apps to access data from this app.
|
||||
*
|
||||
* Requests can be sent via either GET or POST requests. POST is recommended
|
||||
* as it has a lower chance of being logged on the server, exposing unencrypted
|
||||
* user passwords.
|
||||
*/
|
||||
require __DIR__ . '/required.php';
|
||||
require_once __DIR__ . '/lib/login.php';
|
||||
require_once __DIR__ . '/lib/userinfo.php';
|
||||
header("Content-Type: application/json");
|
||||
|
||||
$username = $VARS['username'];
|
||||
$password = $VARS['password'];
|
||||
if (user_exists($username) !== true || authenticate_user($username, $password, $errmsg) !== true) {
|
||||
header("HTTP/1.1 403 Unauthorized");
|
||||
die("\"403 Unauthorized\"");
|
||||
}
|
||||
$userinfo = getUserByUsername($username);
|
||||
|
||||
// query max results
|
||||
$max = 20;
|
||||
if (preg_match("/^[0-9]+$/", $VARS['max']) === 1 && $VARS['max'] <= 1000) {
|
||||
$max = (int) $VARS['max'];
|
||||
}
|
||||
|
||||
switch ($VARS['action']) {
|
||||
case "ping":
|
||||
$out = ["status" => "OK", "maxresults" => $max, "pong" => true];
|
||||
exit(json_encode($out));
|
||||
default:
|
||||
header("HTTP/1.1 400 Bad Request");
|
||||
die("\"400 Bad Request\"");
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
require_once __DIR__ . "/required.php";
|
||||
|
||||
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'])) {
|
||||
$pg = strtolower($_GET['page']);
|
||||
$pg = preg_replace('/[^0-9a-z_]/', "", $pg);
|
||||
if (array_key_exists($pg, PAGES) && file_exists(__DIR__ . "/pages/" . $pg . ".php")) {
|
||||
$pageid = $pg;
|
||||
} else {
|
||||
$pageid = "404";
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="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/material-color.min.css" rel="stylesheet">
|
||||
<link href="static/css/app.css" rel="stylesheet">
|
||||
<?php
|
||||
// custom page styles
|
||||
if (isset(PAGES[$pageid]['styles'])) {
|
||||
foreach (PAGES[$pageid]['styles'] as $style) {
|
||||
echo "<link href=\"$style\" rel=\"stylesheet\">\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</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">
|
||||
<?php
|
||||
if ((SHOW_ICON == "both" || SHOW_ICON == "app") && ICON_POSITION != "menu") {
|
||||
if (MENU_BAR_STYLE != "fixed") {
|
||||
?>
|
||||
<img class="img-responsive banner-image" src="static/img/logo.png" />
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="navbar navbar-inverse navbar-<?php echo MENU_BAR_STYLE; ?>-top">
|
||||
<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 (SHOW_ICON == "both" || SHOW_ICON == "app") {
|
||||
if (MENU_BAR_STYLE == "fixed" || ICON_POSITION == "menu") {
|
||||
$src = "static/img/logo.png";
|
||||
if ($pageid != "home") {
|
||||
$src = "static/img/up-arrow-white.png";
|
||||
}
|
||||
?>
|
||||
<a class="navbar-brand" href="app.php">
|
||||
<img style="height: 35px; padding-bottom: 12px; padding-left: 5px;" src="<?php echo $src; ?>" />
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<a class="navbar-brand" href="app.php">
|
||||
<?php
|
||||
echo SITE_TITLE;
|
||||
?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<?php
|
||||
foreach (PAGES as $id => $pg) {
|
||||
if ($pg['navbar'] === TRUE) {
|
||||
if ($pageid == $id) {
|
||||
?>
|
||||
<li class="active">
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<li>
|
||||
<?php } ?>
|
||||
<a href="app.php?page=<?php echo $id; ?>">
|
||||
<?php
|
||||
if (isset($pg['icon'])) {
|
||||
?>
|
||||
<i class="fa fa-<?php echo $pg['icon']; ?> fa-fw"></i>
|
||||
<?php } ?>
|
||||
<?php lang($pg['title']) ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="<?php echo PORTAL_URL; ?>"><i class="fa fa-user fa-fw"></i> <?php echo $_SESSION['realname'] ?></a></li>
|
||||
<li><a href="action.php?action=signout"><i class="fa fa-sign-out fa-fw"></i> <?php lang("sign out") ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<?php
|
||||
if (MENU_BAR_STYLE == "fixed") {
|
||||
?>
|
||||
<div style="height: 75px;"></div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?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" => strip_tags($_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">×</button>
|
||||
<i class="fa fa-$alerticon"></i> $alertmsg
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
END;
|
||||
}
|
||||
?>
|
||||
<div>
|
||||
<?php
|
||||
include_once __DIR__ . '/pages/' . $pageid . ".php";
|
||||
?>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<?php echo LICENSE_TEXT; ?><br />
|
||||
Copyright © <?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>
|
||||
<?php
|
||||
// custom page scripts
|
||||
if (isset(PAGES[$pageid]['scripts'])) {
|
||||
foreach (PAGES[$pageid]['scripts'] as $script) {
|
||||
echo "<script src=\"$script\"></script>\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "netsyms/business-app-template",
|
||||
"description": "Template for a webapp integrated with a Portal server for authentication.",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"catfan/medoo": "^1.2",
|
||||
"guzzlehttp/guzzle": "^6.2"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Skylar Ittner",
|
||||
"email": "admin@netsyms.com"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,305 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1c8b61c5d506ae016285b99b20040cf0",
|
||||
"packages": [
|
||||
{
|
||||
"name": "catfan/medoo",
|
||||
"version": "v1.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/catfan/Medoo.git",
|
||||
"reference": "00b28046376880e1a7bd3026fa06b4e261bce3fd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/catfan/Medoo/zipball/00b28046376880e1a7bd3026fa06b4e261bce3fd",
|
||||
"reference": "00b28046376880e1a7bd3026fa06b4e261bce3fd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-pdo": "*",
|
||||
"php": ">=5.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pdo_dblib": "For MSSQL or Sybase database on Linux/UNIX platform",
|
||||
"ext-pdo_mysql": "For MySQL or MariaDB database",
|
||||
"ext-pdo_oci": "For Oracle database",
|
||||
"ext-pdo_oci8": "For Oracle version 8 database",
|
||||
"ext-pdo_pqsql": "For PostgreSQL database",
|
||||
"ext-pdo_sqlite": "For SQLite database",
|
||||
"ext-pdo_sqlsrv": "For MSSQL database on Windows platform"
|
||||
},
|
||||
"type": "framework",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Medoo\\": "/src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Angel Lai",
|
||||
"email": "angel@catfan.me"
|
||||
}
|
||||
],
|
||||
"description": "The lightest PHP database framework to accelerate development",
|
||||
"homepage": "https://medoo.in",
|
||||
"keywords": [
|
||||
"database",
|
||||
"lightweight",
|
||||
"mariadb",
|
||||
"mssql",
|
||||
"mysql",
|
||||
"oracle",
|
||||
"php framework",
|
||||
"postgresql",
|
||||
"sql",
|
||||
"sqlite"
|
||||
],
|
||||
"time": "2017-05-22T04:39:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006",
|
||||
"reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle is a PHP HTTP client library",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"client",
|
||||
"curl",
|
||||
"framework",
|
||||
"http",
|
||||
"http client",
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2017-02-28T22:50:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "v1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Promise\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle promises library",
|
||||
"keywords": [
|
||||
"promise"
|
||||
],
|
||||
"time": "2016-12-20T10:07:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"psr/http-message": "~1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||
"keywords": [
|
||||
"http",
|
||||
"message",
|
||||
"request",
|
||||
"response",
|
||||
"stream",
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2017-03-20T17:10:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": []
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
require_once __DIR__ . "/required.php";
|
||||
|
||||
require_once __DIR__ . "/lib/login.php";
|
||||
|
||||
// if we're logged in, we don't need to be here.
|
||||
if ($_SESSION['loggedin']) {
|
||||
header('Location: app.php');
|
||||
}
|
||||
|
||||
/* Authenticate user */
|
||||
$userpass_ok = false;
|
||||
$multiauth = false;
|
||||
if (checkLoginServer()) {
|
||||
if ($VARS['progress'] == "1") {
|
||||
if (!RECAPTCHA_ENABLED || (RECAPTCHA_ENABLED && verifyReCaptcha($VARS['g-recaptcha-response']))) {
|
||||
$errmsg = "";
|
||||
if (authenticate_user($VARS['username'], $VARS['password'], $errmsg)) {
|
||||
switch (get_account_status($VARS['username'])) {
|
||||
case "LOCKED_OR_DISABLED":
|
||||
$alert = lang("account locked", false);
|
||||
break;
|
||||
case "TERMINATED":
|
||||
$alert = lang("account terminated", false);
|
||||
break;
|
||||
case "CHANGE_PASSWORD":
|
||||
$alert = lang("password expired", false);
|
||||
case "NORMAL":
|
||||
$userpass_ok = true;
|
||||
break;
|
||||
case "ALERT_ON_ACCESS":
|
||||
sendLoginAlertEmail($VARS['username']);
|
||||
$userpass_ok = true;
|
||||
break;
|
||||
}
|
||||
if ($userpass_ok) {
|
||||
$_SESSION['passok'] = true; // stop logins using only username and authcode
|
||||
if (userHasTOTP($VARS['username'])) {
|
||||
$multiauth = true;
|
||||
} else {
|
||||
doLoginUser($VARS['username'], $VARS['password']);
|
||||
header('Location: app.php');
|
||||
die("Logged in, go to app.php");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!is_empty($errmsg)) {
|
||||
$alert = lang2("login server error", ['arg' => $errmsg], false);
|
||||
} else {
|
||||
$alert = lang("login incorrect", false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$alert = lang("captcha error", false);
|
||||
}
|
||||
} else if ($VARS['progress'] == "2") {
|
||||
if ($_SESSION['passok'] !== true) {
|
||||
// stop logins using only username and authcode
|
||||
sendError("Password integrity check failed!");
|
||||
}
|
||||
if (verifyTOTP($VARS['username'], $VARS['authcode'])) {
|
||||
if (doLoginUser($VARS['username'])) {
|
||||
header('Location: app.php');
|
||||
die("Logged in, go to app.php");
|
||||
} else {
|
||||
$alert = lang("login server user data error", false);
|
||||
}
|
||||
} else {
|
||||
$alert = lang("2fa incorrect", false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$alert = lang("login server unavailable", false);
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="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/material-color.min.css" rel="stylesheet">
|
||||
<link href="static/css/app.css" rel="stylesheet">
|
||||
<?php if (RECAPTCHA_ENABLED) { ?>
|
||||
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||
<?php } ?>
|
||||
</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">
|
||||
<div>
|
||||
<?php
|
||||
if (SHOW_ICON == "both" || SHOW_ICON == "index") {
|
||||
?>
|
||||
<img class="img-responsive banner-image" src="static/img/logo.png" />
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"><?php lang("sign in"); ?></h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="" method="POST">
|
||||
<?php
|
||||
if (!is_empty($alert)) {
|
||||
?>
|
||||
<div class="alert alert-danger">
|
||||
<i class="fa fa-fw fa-exclamation-triangle"></i> <?php echo $alert; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
if ($multiauth != true) {
|
||||
?>
|
||||
<input type="text" class="form-control" name="username" placeholder="<?php lang("username"); ?>" required="required" autofocus /><br />
|
||||
<input type="password" class="form-control" name="password" placeholder="<?php lang("password"); ?>" required="required" /><br />
|
||||
<?php if (RECAPTCHA_ENABLED) { ?>
|
||||
<div class="g-recaptcha" data-sitekey="<?php echo RECAPTCHA_SITE_KEY; ?>"></div>
|
||||
<br />
|
||||
<?php } ?>
|
||||
<input type="hidden" name="progress" value="1" />
|
||||
<?php
|
||||
} else if ($multiauth) {
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<?php lang("2fa prompt"); ?>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="authcode" placeholder="<?php lang("authcode"); ?>" required="required" autocomplete="off" autofocus /><br />
|
||||
<input type="hidden" name="progress" value="2" />
|
||||
<input type="hidden" name="username" value="<?php echo $VARS['username']; ?>" />
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php lang("continue"); ?>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<?php echo LICENSE_TEXT; ?><br />
|
||||
Copyright © <?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>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
define("STRINGS", [
|
||||
"sign in" => "Sign In",
|
||||
"username" => "Username",
|
||||
"password" => "Password",
|
||||
"continue" => "Continue",
|
||||
"authcode" => "Authentication code",
|
||||
"2fa prompt" => "Enter the six-digit code from your mobile authenticator app.",
|
||||
"2fa incorrect" => "Authentication code incorrect.",
|
||||
"login incorrect" => "Login incorrect.",
|
||||
"login server unavailable" => "Login server unavailable. Try again later or contact technical support.",
|
||||
"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 state error" => "Your account state is not stable. Log out, restart your browser, and try again.",
|
||||
"welcome user" => "Welcome, {user}!",
|
||||
"sign out" => "Sign out",
|
||||
"settings" => "Settings",
|
||||
"options" => "Options",
|
||||
"404 error" => "404 Error",
|
||||
"page not found" => "Page not found.",
|
||||
"invalid parameters" => "Invalid request parameters.",
|
||||
"login server error" => "The login server returned an error: {arg}",
|
||||
"login server user data error" => "The login server refused to provide account information. Try again or contact technical support.",
|
||||
"captcha error" => "There was a problem with the CAPTCHA (robot test). Try again.",
|
||||
"home" => "Home",
|
||||
]);
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
define("MESSAGES", [
|
||||
"invalid_parameters" => [
|
||||
"string" => "invalid parameters",
|
||||
"type" => "danger"
|
||||
],
|
||||
"account_state_error" => [
|
||||
"string" => "account state error",
|
||||
"type" => "danger"
|
||||
],
|
||||
"404_error" => [
|
||||
"string" => "page not found",
|
||||
"type" => "info"
|
||||
]
|
||||
]);
|
@ -0,0 +1,344 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Authentication and account functions. Connects to a Portal instance.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check the login server API for sanity
|
||||
* @return boolean true if OK, else false
|
||||
*/
|
||||
function checkLoginServer() {
|
||||
try {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "ping"
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() != 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Account handling //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Checks the given credentials against the API.
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return boolean True if OK, else false
|
||||
*/
|
||||
function authenticate_user($username, $password, &$errmsg) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "auth",
|
||||
'username' => $username,
|
||||
'password' => $password
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return true;
|
||||
} else {
|
||||
$errmsg = $resp['msg'];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a username exists.
|
||||
* @param String $username
|
||||
*/
|
||||
function user_exists($username) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "userexists",
|
||||
'username' => $username
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK" && $resp['exists'] === true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a UID exists.
|
||||
* @param String $uid
|
||||
*/
|
||||
function uid_exists($uid) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "userexists",
|
||||
'uid' => $uid
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK" && $resp['exists'] === true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account status: NORMAL, TERMINATED, LOCKED_OR_DISABLED,
|
||||
* CHANGE_PASSWORD, or ALERT_ON_ACCESS
|
||||
* @param string $username
|
||||
* @return string
|
||||
*/
|
||||
function get_account_status($username) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "acctstatus",
|
||||
'username' => $username
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['account'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given username has the given permission (or admin access)
|
||||
* @param string $username
|
||||
* @param string $permcode
|
||||
* @return boolean TRUE if the user has the permission (or admin access), else FALSE
|
||||
*/
|
||||
function account_has_permission($username, $permcode) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "permission",
|
||||
'username' => $username,
|
||||
'code' => $permcode
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['has_permission'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Login handling //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Setup $_SESSION values with user data and set loggedin flag to true
|
||||
* @param string $username
|
||||
*/
|
||||
function doLoginUser($username) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "userinfo",
|
||||
'username' => $username
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
var_dump($resp);
|
||||
if ($resp['status'] == "OK") {
|
||||
$userinfo = $resp['data'];
|
||||
$_SESSION['username'] = $username;
|
||||
$_SESSION['uid'] = $userinfo['uid'];
|
||||
$_SESSION['email'] = $userinfo['email'];
|
||||
$_SESSION['realname'] = $userinfo['name'];
|
||||
$_SESSION['loggedin'] = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function simLogin($username, $password) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "login",
|
||||
'username' => $username,
|
||||
'password' => $password
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return true;
|
||||
} else {
|
||||
return $resp['msg'];
|
||||
}
|
||||
}
|
||||
|
||||
function verifyReCaptcha($code) {
|
||||
try {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', "https://www.google.com/recaptcha/api/siteverify", [
|
||||
'form_params' => [
|
||||
'secret' => RECAPTCHA_SECRET_KEY,
|
||||
'response' => $code
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() != 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['success'] === true) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 2-factor authentication //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Check if a user has TOTP setup
|
||||
* @param string $username
|
||||
* @return boolean true if TOTP secret exists, else false
|
||||
*/
|
||||
function userHasTOTP($username) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "hastotp",
|
||||
'username' => $username
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['otp'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a TOTP multiauth code
|
||||
* @global $database
|
||||
* @param string $username
|
||||
* @param int $code
|
||||
* @return boolean true if it's legit, else false
|
||||
*/
|
||||
function verifyTOTP($username, $code) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "verifytotp",
|
||||
'username' => $username,
|
||||
'code' => $code
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['valid'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Get user info for the given username.
|
||||
* @param int $u username
|
||||
* @return [string] Array of [uid, username, name]
|
||||
*/
|
||||
function getUserByUsername($u) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "userinfo",
|
||||
'username' => $u
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['data'];
|
||||
} else {
|
||||
// this shouldn't happen, but in case it does just fake it.
|
||||
return ["name" => $u, "username" => $u, "uid" => $u];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user info for the given UID.
|
||||
* @param int $u user ID
|
||||
* @return [string] Array of [uid, username, name]
|
||||
*/
|
||||
function getUserByID($u) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "userinfo",
|
||||
'uid' => $u
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['data'];
|
||||
} else {
|
||||
// this shouldn't happen, but in case it does just fake it.
|
||||
return ["name" => $u, "username" => $u, "uid" => $u];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the first UID is a manager of the second UID.
|
||||
* @param int $m Manager UID
|
||||
* @param int $e Employee UID
|
||||
* @return boolean
|
||||
*/
|
||||
function isManagerOf($m, $e) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "ismanagerof",
|
||||
'manager' => $m,
|
||||
'employee' => $e,
|
||||
'uid' => 1
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['managerof'];
|
||||
} else {
|
||||
// this shouldn't happen, but in case it does just fake it.
|
||||
return ["name" => $u, "username" => $u, "uid" => $u];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of UIDs the given UID is a manager of.
|
||||
* @param int $manageruid The UID of the manager to find employees for.
|
||||
* @return [int]
|
||||
*/
|
||||
function getManagedUIDs($manageruid) {
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
$response = $client
|
||||
->request('POST', PORTAL_API, [
|
||||
'form_params' => [
|
||||
'key' => PORTAL_KEY,
|
||||
'action' => "getmanaged",
|
||||
'uid' => $manageruid
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() > 299) {
|
||||
sendError("Login server error: " . $response->getBody());
|
||||
}
|
||||
|
||||
$resp = json_decode($response->getBody(), TRUE);
|
||||
if ($resp['status'] == "OK") {
|
||||
return $resp['employees'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
auxiliary.org-netbeans-modules-html-editor-lib.default-html-public-id=-//W3C//DTD HTML 4.01 Transitional//EN
|
||||
include.path=${php.global.include.path}
|
||||
php.version=PHP_70
|
||||
source.encoding=UTF-8
|
||||
src.dir=.
|
||||
tags.asp=false
|
||||
tags.short=false
|
||||
web.root=.
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.php.project</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/php-project/1">
|
||||
<name>QwikClock</name>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
// List of pages and metadata
|
||||
define("PAGES", [
|
||||
"home" => [
|
||||
"title" => "home",
|
||||
"navbar" => true,
|
||||
"icon" => "home"
|
||||
],
|
||||
"404" => [
|
||||
"title" => "404 error"
|
||||
]
|
||||
]);
|
@ -0,0 +1,5 @@
|
||||
<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-warning"><b><?php lang("404 error");?></b><br /> <?php lang("page not found"); ?></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1 @@
|
||||
<h1>Hello World</h1>
|
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file contains global settings and utility functions.
|
||||
*/
|
||||
ob_start(); // allow sending headers after content
|
||||
// Unicode, solves almost all stupid encoding problems
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
|
||||
// l33t $ecurity h4x
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('X-XSS-Protection: 1; mode=block');
|
||||
$session_length = 60 * 60; // 1 hour
|
||||
session_set_cookie_params($session_length, "/", null, false, true);
|
||||
|
||||
session_start(); // stick some cookies in it
|
||||
// renew session cookie
|
||||
setcookie(session_name(), session_id(), time() + $session_length);
|
||||
//
|
||||
// Composer
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Settings file
|
||||
require __DIR__ . '/settings.php';
|
||||
// List of alert messages
|
||||
require __DIR__ . '/lang/messages.php';
|
||||
// text strings (i18n)
|
||||
require __DIR__ . '/lang/' . LANGUAGE . ".php";
|
||||
|
||||
/**
|
||||
* Kill off the running process and spit out an error message
|
||||
* @param string $error error message
|
||||
*/
|
||||
function sendError($error) {
|
||||
die("<!DOCTYPE html><html><head><title>Error</title></head><body><h1 style='color: red; font-family: sans-serif; font-size:100%;'>" . htmlspecialchars($error) . "</h1></body></html>");
|
||||
}
|
||||
|
||||
date_default_timezone_set(TIMEZONE);
|
||||
|
||||
// Database settings
|
||||
// Also inits database and stuff
|
||||
use Medoo\Medoo;
|
||||
|
||||
$database;
|
||||
try {
|
||||
$database = new Medoo([
|
||||
'database_type' => DB_TYPE,
|
||||
'database_name' => DB_NAME,
|
||||
'server' => DB_SERVER,
|
||||
'username' => DB_USER,
|
||||
'password' => DB_PASS,
|
||||
'charset' => DB_CHARSET
|
||||
]);
|
||||
} catch (Exception $ex) {
|
||||
//header('HTTP/1.1 500 Internal Server Error');
|
||||
sendError("Database error. Try again later. $ex");
|
||||
}
|
||||
|
||||
|
||||
if (!DEBUG) {
|
||||
error_reporting(0);
|
||||
} else {
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 'On');
|
||||
}
|
||||
|
||||
|
||||
$VARS;
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$VARS = $_POST;
|
||||
define("GET", false);
|
||||
} else {
|
||||
$VARS = $_GET;
|
||||
define("GET", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a string or whatever is empty.
|
||||
* @param $str The thingy to check
|
||||
* @return boolean True if it's empty or whatever.
|
||||
*/
|
||||
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 {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
function dieifnotloggedin() {
|
||||
if ($_SESSION['loggedin'] != true) {
|
||||
sendError("Session expired. Please log out and log in again.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the previous database action had a problem.
|
||||
* @param array $specials int=>string array with special response messages for SQL errors
|
||||
*/
|
||||
function checkDBError($specials = []) {
|
||||
global $database;
|
||||
$errors = $database->error();
|
||||
if (!is_null($errors[1])) {
|
||||
foreach ($specials as $code => $text) {
|
||||
if ($errors[1] == $code) {
|
||||
sendError($text);
|
||||
}
|
||||
}
|
||||
sendError("A database error occurred:<br /><code>" . $errors[2] . "</code>");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* http://stackoverflow.com/a/20075147/2534036
|
||||
*/
|
||||
if (!function_exists('base_url')) {
|
||||
|
||||
function base_url($atRoot = FALSE, $atCore = FALSE, $parse = FALSE) {
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
$http = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
|
||||
$hostname = $_SERVER['HTTP_HOST'];
|
||||
$dir = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
|
||||
|
||||
$core = preg_split('@/@', str_replace($_SERVER['DOCUMENT_ROOT'], '', realpath(dirname(__FILE__))), NULL, PREG_SPLIT_NO_EMPTY);
|
||||
$core = $core[0];
|
||||
|
||||
$tmplt = $atRoot ? ($atCore ? "%s://%s/%s/" : "%s://%s/") : ($atCore ? "%s://%s/%s/" : "%s://%s%s");
|
||||
$end = $atRoot ? ($atCore ? $core : $hostname) : ($atCore ? $core : $dir);
|
||||
$base_url = sprintf($tmplt, $http, $hostname, $end);
|
||||
} else
|
||||
$base_url = 'http://localhost/';
|
||||
|
||||
if ($parse) {
|
||||
$base_url = parse_url($base_url);
|
||||
if (isset($base_url['path']))
|
||||
if ($base_url['path'] == '/')
|
||||
$base_url['path'] = '';
|
||||
}
|
||||
|
||||
return $base_url;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function redirectIfNotLoggedIn() {
|
||||
if ($_SESSION['loggedin'] !== TRUE) {
|
||||
header('Location: ' . URL . '/index.php');
|
||||
die();
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
// Whether to show debugging data in output.
|
||||
// DO NOT SET TO TRUE IN PRODUCTION!!!
|
||||
define("DEBUG", false);
|
||||
|
||||
// Database connection settings
|
||||
// See http://medoo.in/api/new for info
|
||||
define("DB_TYPE", "mysql");
|
||||
define("DB_NAME", "qwikclock");
|
||||
define("DB_SERVER", "localhost");
|
||||
define("DB_USER", "qwikclock");
|
||||
define("DB_PASS", "");
|
||||
define("DB_CHARSET", "utf8");
|
||||
|
||||
// Name of the app.
|
||||
define("SITE_TITLE", "QwikClock");
|
||||
|
||||
// Which pages to show the app icon on:
|
||||
// index, app, both, none
|
||||
define("SHOW_ICON", "both");
|
||||
// Where to put the icon: top or menu
|
||||
// Overridden to 'menu' if MENU_BAR_STYLE is 'fixed'.
|
||||
define("ICON_POSITION", "menu");
|
||||
// App menu bar style: fixed or static
|
||||
define("MENU_BAR_STYLE", "fixed");
|
||||
|
||||
// URL of the Business Portal API endpoint
|
||||
define("PORTAL_API", "http://localhost/portal/api.php");
|
||||
// URL of the Portal home page
|
||||
define("PORTAL_URL", "http://localhost/portal/home.php");
|
||||
// Business Portal API Key
|
||||
define("PORTAL_KEY", "123");
|
||||
|
||||
// For supported values, see http://php.net/manual/en/timezones.php
|
||||
define("TIMEZONE", "America/Denver");
|
||||
|
||||
// Base URL for site links.
|
||||
define('URL', 'http://localhost/qwikclock');
|
||||
|
||||
// Use reCAPTCHA on login screen
|
||||
// https://www.google.com/recaptcha/
|
||||
define("RECAPTCHA_ENABLED", FALSE);
|
||||
define('RECAPTCHA_SITE_KEY', '');
|
||||
define('RECAPTCHA_SECRET_KEY', '');
|
||||
|
||||
// See lang folder for language options
|
||||
define('LANGUAGE', "en_us");
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// /!\ Warning: Changing these values may /!\ //
|
||||
// /!\ violate the terms of your license agreement! /!\ //
|
||||
//////////////////////////////////////////////////////////////
|
||||
define("LICENSE_TEXT", "<b>Personal, Non-commercial Use Only</b>");
|
||||
define("COPYRIGHT_NAME", "Netsyms Technologies");
|
||||
//////////////////////////////////////////////////////////////
|
@ -0,0 +1,58 @@
|
||||
.banner-image {
|
||||
max-height: 100px;
|
||||
margin: 2em auto;
|
||||
border: 1px solid grey;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 10em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================
|
||||
THEMING
|
||||
==============================
|
||||
|
||||
Changing the .navbar-inverse background should be enough on modern browsers.
|
||||
If this app is to be used on IE < 9 (not supported), also set a background-color
|
||||
to replace the rgba()s.
|
||||
|
||||
To use a material-color.css navbar theme, remove all the theming styles in this
|
||||
file and add a .navbar-[color] class to the navbar in app.php.
|
||||
*/
|
||||
|
||||
/* navbar background */
|
||||
.navbar-inverse {
|
||||
/* background-color: green; */
|
||||
}
|
||||
|
||||
/* Selected page background */
|
||||
.navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus {
|
||||
background: rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form {
|
||||
border-color: rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-toggle .icon-bar {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-brand {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-link {
|
||||
color: white;
|
||||
}
|
檔案差異因為一行或多行太長而無法顯示
檔案差異因為一行或多行太長而無法顯示
檔案差異因為檔案過大而無法顯示
載入差異
檔案差異因為一行或多行太長而無法顯示
未顯示二進位檔案。
未顯示二進位檔案。
檔案差異因為檔案過大而無法顯示
載入差異
之後 寬度: | 高度: | 大小: 434 KiB |
未顯示二進位檔案。
未顯示二進位檔案。
未顯示二進位檔案。
未顯示二進位檔案。
之後 寬度: | 高度: | 大小: 12 KiB |
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512.00001 512.00001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:export-filename="/home/skylar/Documents/Projects/Sources/WebAppTemplate/static/img/logo.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="-493.3276 : 245.89848 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="464.45088 : 245.89848 : 1"
|
||||
inkscape:persp3d-origin="-14.438371 : 160.56515 : 1"
|
||||
id="perspective4236" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="-135.9681"
|
||||
inkscape:cy="352.66131"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-540.36216)">
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.74509804"
|
||||
id="rect4726"
|
||||
width="512"
|
||||
height="512"
|
||||
x="0"
|
||||
y="540.36218"
|
||||
rx="50"
|
||||
ry="50" />
|
||||
<path
|
||||
id="path4348"
|
||||
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:9.87128067;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 132.93564,682.51771 213.96788,-43.14304 0,313.97496 -213.96788,-37.9643 z m 213.96788,-43.14304 0,313.97496 32.16084,-45.18373 0,-217.44396 z m -213.96788,43.14304 213.96788,-43.14304 32.16084,51.34727 -167.21823,22.47784 z m 78.91049,30.68207 167.21823,-22.47784 0,217.44396 -167.21823,-19.77968 z m -78.91049,-30.68207 0,232.86762 78.91049,-26.99911 0,-175.18644 z m 0,232.86762 213.96788,37.9643 32.16084,-45.18373 -167.21823,-19.77968 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
之後 寬度: | 高度: | 大小: 2.9 KiB |
未顯示二進位檔案。
之後 寬度: | 高度: | 大小: 516 B |
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64.000001 63.999997"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="up-arrow-black.svg"
|
||||
inkscape:export-filename="/home/skylar/Documents/Projects/Sources/SimpleInventory/static/img/up-arrow-black.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="66.826957"
|
||||
inkscape:cy="-6.0149722"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-83.334319,-53.898981)">
|
||||
<g
|
||||
id="g4224"
|
||||
transform="matrix(0.69842965,0,0,0.69842965,25.127004,31.746558)"
|
||||
style="fill:#000000;fill-opacity:1">
|
||||
<rect
|
||||
ry="7.1589174"
|
||||
rx="7.1589174"
|
||||
y="72.534538"
|
||||
x="85.33432"
|
||||
height="10"
|
||||
width="90"
|
||||
id="rect4136"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
|
||||
ry="7.1589174"
|
||||
rx="7.1589174"
|
||||
y="-12.636598"
|
||||
x="112.29343"
|
||||
height="10"
|
||||
width="60"
|
||||
id="rect4136-6-7"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"
|
||||
ry="7.1589174"
|
||||
rx="7.1589174"
|
||||
y="112.287"
|
||||
x="2.6430364"
|
||||
height="10"
|
||||
width="60"
|
||||
id="rect4136-6-7-5"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
之後 寬度: | 高度: | 大小: 3.0 KiB |
未顯示二進位檔案。
之後 寬度: | 高度: | 大小: 538 B |
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64.000001 63.999997"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="up-arrow-white.svg"
|
||||
inkscape:export-filename="/home/skylar/Documents/Projects/Sources/SimpleInventory/static/img/up-arrow-white.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="66.826957"
|
||||
inkscape:cy="-6.0149722"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-83.334319,-53.898981)">
|
||||
<g
|
||||
id="g4224"
|
||||
transform="matrix(0.69842965,0,0,0.69842965,25.127004,31.746558)"
|
||||
style="fill:#ffffff;fill-opacity:1">
|
||||
<rect
|
||||
ry="7.1589174"
|
||||
rx="7.1589174"
|
||||
y="72.534538"
|
||||
x="85.33432"
|
||||
height="10"
|
||||
width="90"
|
||||
id="rect4136"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
|
||||
ry="7.1589174"
|
||||
rx="7.1589174"
|
||||
y="-12.636598"
|
||||
x="112.29343"
|
||||
height="10"
|
||||
width="60"
|
||||
id="rect4136-6-7"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"
|
||||
ry="7.1589174"
|
||||
rx="7.1589174"
|
||||
y="112.287"
|
||||
x="2.6430364"
|
||||
height="10"
|
||||
width="60"
|
||||
id="rect4136-6-7-5"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
之後 寬度: | 高度: | 大小: 3.0 KiB |
@ -0,0 +1,23 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
/* Fade out alerts */
|
||||
$(".alert .close").click(function (e) {
|
||||
$(this).parent().fadeOut("slow");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Remove feedback params from the URL so they don't stick around too long
|
||||
*/
|
||||
function getniceurl() {
|
||||
var url = window.location.search;
|
||||
url = url.substring(url.lastIndexOf("/") + 1);
|
||||
url = url.replace(/&?msg=([^&]$|[^&]*)/i, "");
|
||||
return url;
|
||||
}
|
||||
try {
|
||||
window.history.replaceState("", "", getniceurl());
|
||||
} catch (ex) {
|
||||
|
||||
}
|
檔案差異因為一行或多行太長而無法顯示
檔案差異因為一行或多行太長而無法顯示
載入中…
新增問題並參考