diff --git a/Dockerfile b/Dockerfile
index fd40ac1..610dbda 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,16 +1,15 @@
-FROM composer:1.7
+FROM composer:2.2
-ENV TINI_VERSION 0.18.0-r0
-
-RUN apk add --no-cache tini=$TINI_VERSION
-
-ADD . /src/app/
+RUN apk add --no-cache tini tzdata
WORKDIR /src/app
-RUN composer install
+COPY . .
-RUN cp includes/config.environment.inc.php includes/config.inc.php
+RUN set -xe; \
+ composer install; \
+ cp includes/config.environment.inc.php includes/config.inc.php
+ENV PORT 80
EXPOSE 80
-ENTRYPOINT [ "tini", "--", "php", "-S", "0.0.0.0:80" ]
+ENTRYPOINT [ "sh", "-c", "tini -- php -S 0.0.0.0:$PORT" ]
diff --git a/README.markdown b/README.markdown
index ddf39d3..0938c08 100644
--- a/README.markdown
+++ b/README.markdown
@@ -41,7 +41,7 @@ git clone https://github.com/nrk/predis.git vendor
Docker Image
============
-A public [phpRedisAdmin Docker image](https://hub.docker.com/r/erikdubbelboer/phpredisadmin/) is available on Docker Hub [automatically built](https://docs.docker.com/docker-hub/builds/) from latest source.
+A public [phpRedisAdmin Docker image](https://hub.docker.com/r/erikdubbelboer/phpredisadmin/) is available on Docker Hub built from the latest tag.
The file ```includes/config.environment.inc.php``` is used as the configuration file to allow environment variables to be used as configuration values.
Example:
```
@@ -55,7 +55,10 @@ Environment variables summary
* ``REDIS_1_HOST`` - define host of the Redis server
* ``REDIS_1_NAME`` - define name of the Redis server
* ``REDIS_1_PORT`` - define port of the Redis server
+* ``REDIS_1_SCHEME`` - define scheme of the Redis server (tcp or tls)
* ``REDIS_1_AUTH`` - define password of the Redis server
+* ``REDIS_1_AUTH_FILE`` - define file containing the password of the Redis server
+* ``REDIS_1_DATABASES`` - You can modify you config to prevent phpRedisAdmin from using CONFIG command
* ``ADMIN_USER`` - define username for user-facing Basic Auth
* ``ADMIN_PASS`` - define password for user-facing Basic Auth
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..1627ff2
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,13 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+| ------- | ------------------ |
+| 1.13.x | :white_check_mark: |
+| 1.12.x | :white_check_mark: |
+| < 1.12 | :x: |
+
+## Reporting a Vulnerability
+
+Vulnerabilities can be emailed to erik@dubbelboer.com
diff --git a/composer.json b/composer.json
index f66ba98..3b3ab81 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "erik-dubbelboer/php-redis-admin",
"description": "Simple web interface to manage Redis databases.",
- "version": "1.13.2",
+ "version": "1.24.0",
"license": "CC-BY-3.0",
"homepage": "https://github.com/ErikDubbelboer/phpRedisAdmin",
"authors": [
@@ -13,8 +13,11 @@
}
],
"require": {
- "predis/predis": "1.1.x-dev"
+ "ext-mbstring": "*",
+ "ext-json": "*",
+ "predis/predis": "v2.3.0",
+ "paragonie/random_compat": ">=2"
},
"minimum-stability": "stable",
- "target-dir": "ErikDubbelboer/phpRedisAdmin"
+ "target-dir": "ErikDubbelboer/phpRedisAdmin"
}
diff --git a/composer.lock b/composer.lock
index ac3a614..f724f31 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,31 +4,82 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "0c346d5e2f2e0897260911e1b2966180",
+ "content-hash": "401ff61cebe5223d003a47192d7c3d6a",
"packages": [
+ {
+ "name": "paragonie/random_compat",
+ "version": "v9.99.100",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">= 7"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*",
+ "vimeo/psalm": "^1"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com/"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "polyfill",
+ "pseudorandom",
+ "random"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/random_compat/issues",
+ "source": "https://github.com/paragonie/random_compat"
+ },
+ "time": "2020-10-15T08:29:30+00:00"
+ },
{
"name": "predis/predis",
- "version": "v1.1.x-dev",
+ "version": "v2.3.0",
"source": {
"type": "git",
- "url": "https://github.com/nrk/predis.git",
- "reference": "111d100ee389d624036b46b35ed0c9ac59c71313"
+ "url": "https://github.com/predis/predis.git",
+ "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nrk/predis/zipball/111d100ee389d624036b46b35ed0c9ac59c71313",
- "reference": "111d100ee389d624036b46b35ed0c9ac59c71313",
+ "url": "https://api.github.com/repos/predis/predis/zipball/bac46bfdb78cd6e9c7926c697012aae740cb9ec9",
+ "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9",
"shasum": ""
},
"require": {
- "php": ">=5.3.9"
+ "php": "^7.2 || ^8.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.8"
+ "friendsofphp/php-cs-fixer": "^3.3",
+ "phpstan/phpstan": "^1.9",
+ "phpunit/phpunit": "^8.0 || ^9.4"
},
"suggest": {
- "ext-curl": "Allows access to Webdis when paired with phpiredis",
- "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol"
+ "ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
},
"type": "library",
"autoload": {
@@ -42,29 +93,41 @@
],
"authors": [
{
- "name": "Daniele Alessandri",
- "email": "suppakilla@gmail.com",
- "homepage": "http://clorophilla.net/"
+ "name": "Till Krüss",
+ "homepage": "https://till.im/",
+ "role": "Maintainer"
}
],
- "description": "Flexible and feature-complete Redis client for PHP and HHVM",
- "homepage": "http://github.com/nrk/predis",
+ "description": "A flexible and feature-complete Redis client for PHP.",
+ "homepage": "http://github.com/predis/predis",
"keywords": [
"nosql",
"predis",
"redis"
],
- "time": "2017-07-12T14:39:17+00:00"
+ "support": {
+ "issues": "https://github.com/predis/predis/issues",
+ "source": "https://github.com/predis/predis/tree/v2.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/tillkruss",
+ "type": "github"
+ }
+ ],
+ "time": "2024-11-21T20:00:02+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": {
- "predis/predis": 20
- },
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
- "platform": [],
- "platform-dev": []
+ "platform": {
+ "ext-mbstring": "*",
+ "ext-json": "*"
+ },
+ "platform-dev": {},
+ "plugin-api-version": "2.6.0"
}
diff --git a/css/frame.css b/css/frame.css
index e54ca9e..7cf935d 100644
--- a/css/frame.css
+++ b/css/frame.css
@@ -14,7 +14,6 @@ margin-left: -8em;
}
form .button {
-margin-left: -7em;
}
@@ -53,3 +52,13 @@ float: left;
margin: 1em;
}
+
+.exception {
+border: 1px solid #ff0000;
+background-color: rgba(255, 0, 0, 0.2);
+color: #880000;
+padding: 10px;
+border-radius: 5px;
+margin: 20px;
+}
+
diff --git a/delete.php b/delete.php
index cde8539..c329919 100644
--- a/delete.php
+++ b/delete.php
@@ -1,13 +1,13 @@
del($key);
}
@@ -73,4 +73,3 @@
die('?view&s=' . $server['id'] . '&d=' . $server['db'] . '&key=' . urlencode($keys[0]));
}
-?>
diff --git a/docker-compose.yml b/docker-compose.yml
index dab64b9..5ef83df 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,15 +1,16 @@
-phpredisadmin:
- build: .
- environment:
- - ADMIN_USER=admin
- - ADMIN_PASS=admin
- - REDIS_1_HOST=redis
- - REDIS_1_PORT=6379
- links:
- - redis
- ports:
- - "80:80"
+services:
+ phpredisadmin:
+ build: .
+ environment:
+ - ADMIN_USER=admin
+ - ADMIN_PASS=admin
+ - REDIS_1_HOST=redis
+ - REDIS_1_PORT=6379
+ links:
+ - redis
+ ports:
+ - "80:80"
-redis:
- image: redis
- command: --loglevel verbose
+ redis:
+ image: redis
+ command: --loglevel verbose
diff --git a/edit.php b/edit.php
index 0940503..998012c 100644
--- a/edit.php
+++ b/edit.php
@@ -2,8 +2,7 @@
require_once 'includes/common.inc.php';
-
-
+global $redis, $config, $csrfToken, $server;
// Are we editing or creating a new key?
$edit = false;
@@ -35,72 +34,83 @@
die('ERROR: could not encode value');
}
- // String
- if ($_POST['type'] == 'string') {
- $redis->set($key, $value);
- }
-
- // Hash
- else if (($_POST['type'] == 'hash') && isset($_POST['hkey'])) {
- if (strlen($_POST['hkey']) > $config['maxkeylen']) {
- die('ERROR: Your hash key is to long (max length is '.$config['maxkeylen'].')');
+ try {
+ // String
+ if ($_POST['type'] == 'string') {
+ $redis->set($key, $value);
}
- if ($edit && !$redis->hExists($key, input_convert($_POST['hkey']))) {
- $redis->hDel($key, input_convert($_GET['hkey']));
+ // Hash
+ else if (($_POST['type'] == 'hash') && isset($_POST['hkey'])) {
+ if (strlen($_POST['hkey']) > $config['maxkeylen']) {
+ die('ERROR: Your hash key is to long (max length is '.$config['maxkeylen'].')');
+ }
+
+ if ($edit && !$redis->hExists($key, input_convert($_POST['hkey']))) {
+ $redis->hDel($key, input_convert($_GET['hkey']));
+ }
+
+ $redis->hSet($key, input_convert($_POST['hkey']), $value);
}
- $redis->hSet($key, input_convert($_POST['hkey']), $value);
- }
+ // List
+ else if (($_POST['type'] == 'list') && isset($_POST['index'])) {
+ $size = $redis->lLen($key);
+
+ if (($_POST['index'] == '') ||
+ ($_POST['index'] == $size)) {
+ // Push it at the end
+ $redis->rPush($key, $value);
+ } else if ($_POST['index'] == -1) {
+ // Push it at the start
+ $redis->lPush($key, $value);
+ } else if (($_POST['index'] >= 0) &&
+ ($_POST['index'] < $size)) {
+ // Overwrite an index
+ $redis->lSet($key, input_convert($_POST['index']), $value);
+ } else {
+ die('ERROR: Out of bounds index');
+ }
+ }
- // List
- else if (($_POST['type'] == 'list') && isset($_POST['index'])) {
- $size = $redis->lLen($key);
-
- if (($_POST['index'] == '') ||
- ($_POST['index'] == $size)) {
- // Push it at the end
- $redis->rPush($key, $value);
- } else if ($_POST['index'] == -1) {
- // Push it at the start
- $redis->lPush($key, $value);
- } else if (($_POST['index'] >= 0) &&
- ($_POST['index'] < $size)) {
- // Overwrite an index
- $redis->lSet($key, input_convert($_POST['index']), $value);
- } else {
- die('ERROR: Out of bounds index');
+ // Set
+ else if ($_POST['type'] == 'set') {
+ if ($_POST['value'] != $_POST['oldvalue']) {
+ // The only way to edit a Set value is to add it and remove the old value.
+ $redis->sRem($key, encodeOrDecode('save', $key, input_convert($_POST['oldvalue'])));
+ $redis->sAdd($key, $value);
+ }
}
- }
- // Set
- else if ($_POST['type'] == 'set') {
- if ($_POST['value'] != $_POST['oldvalue']) {
- // The only way to edit a Set value is to add it and remove the old value.
- $redis->sRem($key, encodeOrDecode('save', $key, input_convert($_POST['oldvalue'])));
- $redis->sAdd($key, $value);
+ // ZSet
+ else if (($_POST['type'] == 'zset') && isset($_POST['score']) && is_numeric($_POST['score'])) {
+ // The only way to edit a ZSet value is to add it and remove the old value.
+ $redis->zRem($key, encodeOrDecode('save', $key, input_convert($_POST['oldvalue'])));
+ $redis->zAdd($key, input_convert($_POST['score']), $value);
}
- }
- // ZSet
- else if (($_POST['type'] == 'zset') && isset($_POST['score'])) {
- // The only way to edit a ZSet value is to add it and remove the old value.
- $redis->zRem($key, encodeOrDecode('save', $key, input_convert($_POST['oldvalue'])));
- $redis->zAdd($key, input_convert($_POST['score']), $value);
- }
+ // Refresh the top so the key tree is updated.
+ require 'includes/header.inc.php';
- // Refresh the top so the key tree is updated.
- require 'includes/header.inc.php';
+ ?>
+
+
-
-
+
+
getMessage() ?>
+
+
+?>
\ No newline at end of file
diff --git a/export.php b/export.php
index c886e46..d17839e 100644
--- a/export.php
+++ b/export.php
@@ -2,6 +2,7 @@
require_once 'includes/common.inc.php';
+global $redis, $config, $csrfToken, $server;
// Export to redis-cli commands
function export_redis($key, $filter = false, $transform = false) {
@@ -15,7 +16,7 @@ function export_redis($key, $filter = false, $transform = false) {
$outputKey = str_replace($filter, $transform, $key);
else
$outputKey = $key;
-
+
// String
if ($type == 'string') {
echo 'SET "',addslashes($outputKey),'" "',addslashes($redis->get($key)),'"',PHP_EOL;
@@ -124,7 +125,7 @@ function export_json($key) {
// JSON
if ($_POST['type'] == 'json') {
-
+
// Single key
if (isset($_GET['key'])) {
echo json_encode(export_json($_GET['key']));
@@ -137,13 +138,13 @@ function export_json($key) {
// if we have a filter and no match, nothing to do
if($filter !== false && stripos($key, $filter) === false)
continue;
-
+
// we rename the keys as necessary
if($filter !== false && $transform !== false)
$outputKey = str_replace($filter, $transform, $key);
else
$outputKey = $key;
-
+
$vals[$outputKey] = export_json($key);
}
@@ -165,7 +166,7 @@ function export_json($key) {
// if we have a filter and no match, we skip
if($filter !== false && stripos($key, $filter) === false)
continue;
-
+
export_redis($key, $filter, $transform);
}
}
@@ -187,6 +188,7 @@ function export_json($key) {
Export
flushdb();
diff --git a/import.php b/import.php
index 1786164..5e5a89e 100644
--- a/import.php
+++ b/import.php
@@ -1,9 +1,7 @@
Import
'unix', 'path' => $server['path']));
} else {
- $redis = !$server['port'] ? new Predis\Client($server['host']) : new Predis\Client('tcp://'.$server['host'].':'.$server['port']);
+ $redis = !$server['port'] ? new Predis\Client($server['host']) : new Predis\Client($server['scheme'].'://'.$server['host'].':'.$server['port']);
}
try {
@@ -118,11 +148,12 @@
}
}
+if (!isset($config['login']) && !empty($config['login_as_acl_auth'])) {
+ require_once PHPREDIS_ADMIN_PATH . '/includes/login_acl.inc.php';
+}
if ($server['db'] != 0) {
if (!$redis->select($server['db'])) {
die('ERROR: Selecting database failed ('.$server['host'].':'.$server['port'].','.$server['db'].')');
}
}
-
-?>
diff --git a/includes/config.environment.inc.php b/includes/config.environment.inc.php
index 587899c..06a06fe 100644
--- a/includes/config.environment.inc.php
+++ b/includes/config.environment.inc.php
@@ -2,6 +2,19 @@
include 'config.sample.inc.php';
+// get configs from environment variables
+$config['cookie_auth'] = getenv('COOKIE_AUTH') ?: false;
+$config['count_elements_page'] = getenv('COUNT_ELEMENTS_PAGE') ?: 100;
+$config['faster'] = getenv('FASTER') ?: true;
+$config['filter'] = getenv('FILTER') ?: '*';
+$config['hideEmptyDBs'] = getenv('HIDE_EMPTY_DBS') ?: false;
+$config['keys'] = getenv('KEYS') ?: false;
+$config['maxkeylen'] = getenv('MAX_KEY_LEN') ?: 100;
+$config['scansize'] = getenv('SCAN_SIZE') ?: 1000;
+$config['scanmax'] = getenv('SCAN_MAX') ?: 1000;
+$config['seperator'] = getenv('SEPERATOR') ?: ':';
+$config['showEmptyNamespaceAsKey'] = getenv('SHOW_EMPTY_NAMESPACE_AS_KEY') ?: false;
+
$admin_user = getenv('ADMIN_USER');
$admin_pass = getenv('ADMIN_PASS');
@@ -23,7 +36,12 @@
$server_name = getenv($prefix . 'NAME');
$server_host = getenv($prefix . 'HOST');
$server_port = getenv($prefix . 'PORT');
- $server_auth = getenv($prefix . 'AUTH');
+ $server_scheme = getenv($prefix . 'SCHEME');
+ if (getenv($prefix . 'AUTH_FILE') !== false) {
+ $server_auth = file_get_contents(getenv($prefix . 'AUTH_FILE'));
+ } else {
+ $server_auth = getenv($prefix . 'AUTH');
+ }
$server_databases = getenv($prefix . 'DATABASES');
if (empty($server_host)) {
@@ -33,29 +51,36 @@
if (empty($server_name)) {
$server_name = $server_host;
}
-
+
if (empty($server_auth)) {
$server_auth = "";
- }
+ }
- if (empty($server_port)) {
+ if (empty($server_port) && strpos($server_host, ':') === false) {
$server_port = 6379;
}
+ if (empty($server_scheme)) {
+ $server_scheme = 'tcp';
+ }
+
$config['servers'][] = array(
- 'name' => $server_name,
- 'host' => $server_host,
- 'port' => $server_port,
- 'filter' => '*',
+ 'name' => $server_name,
+ 'host' => $server_host,
+ 'port' => $server_port,
+ 'filter' => $config['filter'],
+ 'scansize' => $config['scansize'],
+ 'scanmax' => $config['scanmax'],
+ 'scheme' => $server_scheme,
);
-
+
if (!empty($server_auth)) {
$config['servers'][$i-1]['auth'] = $server_auth;
- }
-
+ }
+
if (!empty($server_databases)) {
$config['servers'][$i-1]['databases'] = $server_databases;
- }
+ }
$i++;
}
diff --git a/includes/config.sample.inc.php b/includes/config.sample.inc.php
index 10ed201..923a60c 100644
--- a/includes/config.sample.inc.php
+++ b/includes/config.sample.inc.php
@@ -32,7 +32,8 @@
'flush' => false, // Set to true to enable the flushdb button for this instance.
'charset' => 'cp1251', // Keys and values are stored in redis using this encoding (default utf-8).
'keys' => false, // Use the old KEYS command instead of SCAN to fetch all keys for this server (default uses config default).
- 'scansize' => 1000 // How many entries to fetch using each SCAN command for this server (default uses config default).
+ 'scansize' => 1000, // How many entries to fetch using each SCAN command for this server (default uses config default).
+ 'scanmax' => 1000, // In each query, SCAN command may be executed several times. To shorten the duration, it is recommended to limit the total number of entries to fetch (default uses config default).
),*/
),
@@ -60,6 +61,12 @@
)
),*/
+ // Uncomment to enable login as ACL authentication (won't work if 'login' or 'auth' is also used)
+ // Only support using one server at this moment.
+ // If you set the default user off, browsers will be redirected to login page.
+ // The user and password will be stored in browser as plaintext so using HTTPS is strongly recommended.
+ // 'login_as_acl_auth' => true,
+
// Use HTML form/cookie-based auth instead of HTTP Basic/Digest auth
'cookie_auth' => false,
@@ -83,5 +90,8 @@
'keys' => false,
// How many entries to fetch using each SCAN command.
- 'scansize' => 1000
+ 'scansize' => 1000,
+
+ // The total number of entries to fetch. Set to 0 or -1 for no limit.
+ 'scanmax' => 0
);
diff --git a/includes/header.inc.php b/includes/header.inc.php
index aa618f1..7679bd6 100644
--- a/includes/header.inc.php
+++ b/includes/header.inc.php
@@ -4,6 +4,7 @@
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: private');
+header('X-Frame-Options: sameorigin');
?>
@@ -35,5 +36,9 @@
+
+
diff --git a/includes/login.inc.php b/includes/login.inc.php
index 75ed28d..8cfb26d 100644
--- a/includes/login.inc.php
+++ b/includes/login.inc.php
@@ -56,7 +56,7 @@ function authHttpDigest()
$response = md5($password.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']));
- if ($data['response'] != $response) {
+ if ($data['response'] !== $response) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.$opaque.'"');
die('Invalid username and/or password combination.');
diff --git a/includes/login_acl.inc.php b/includes/login_acl.inc.php
new file mode 100644
index 0000000..e8b7d72
--- /dev/null
+++ b/includes/login_acl.inc.php
@@ -0,0 +1,100 @@
+auth($login['username'], $login['password']);
+ } catch (Predis\Response\ServerException $exception) {
+ return false;
+ }
+ return true;
+}
+
+// This fill will perform HTTP basic authentication. The authentication data will be sent and stored as plaintext
+// Please make sure to use HTTPS proxy such as Apache or Nginx to prevent traffic eavesdropping.
+function authHttpBasic()
+{
+ $realm = 'phpRedisAdmin';
+
+ if (!isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
+ try {
+ global $redis;
+ $redis->ping();
+ } catch (Predis\Response\ServerException $exception) {
+ header('HTTP/1.1 401 Unauthorized');
+ header('WWW-Authenticate: Basic realm="' . $realm . '"');
+ die('NOAUTH -- Authentication required');
+ }
+ }
+
+ $login = [
+ 'username' => $_SERVER['PHP_AUTH_USER'],
+ 'password' => $_SERVER['PHP_AUTH_PW'],
+ ];
+
+ if (!authCheck($login)) {
+ header('HTTP/1.1 401 Unauthorized');
+ header('WWW-Authenticate: Basic realm="' . $realm . '"');
+ die('NOAUTH -- Authentication required');
+ }
+
+ return $login;
+}
+
+// Perform auth using a standard HTML