4 Commits

Author SHA1 Message Date
6d19d869c8 Merge branch 'master' into feature_multimodeOperation 2018-04-16 14:52:09 +02:00
6143a23dd8 autoformat to reduce merge conflicts 2018-04-16 14:29:40 +02:00
f808615f22 start implementing multiple modes for operation
- synapse: Only trigger register calls and do not store anything for longterm
- local: Provide an identity store and register to the own backend
2018-04-15 21:36:24 +02:00
ffce2fc28b run some autoformat 2018-04-04 20:43:24 +02:00
23 changed files with 247 additions and 597 deletions

3
.gitignore vendored
View File

@@ -1,5 +1,2 @@
config.php config.php
db_file.sqlite db_file.sqlite
# do not track sources which will be built by composer
/vendor/

View File

@@ -14,9 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/helpers.php");
class MatrixConnection { class MatrixConnection {
private $hs; private $hs;
@@ -48,8 +45,12 @@ class MatrixConnection {
$url = "https://" . $this->hs . "/_matrix/client/r0/rooms/" $url = "https://" . $this->hs . "/_matrix/client/r0/rooms/"
. urlencode($room_id) . "/send/m.room.message?access_token=" . $this->at; . urlencode($room_id) . "/send/m.room.message?access_token=" . $this->at;
$handle = getCurlHandle($url); $handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($send_message)); curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($send_message));
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
$response = $this->exec_curl_request($handle); $response = $this->exec_curl_request($handle);
return isset($response["event_id"]); return isset($response["event_id"]);
@@ -69,62 +70,40 @@ class MatrixConnection {
} }
$url = "https://" . $this->hs . "/_matrix/client/r0/profile/@" . $username . ":" . $this->hs; $url = "https://" . $this->hs . "/_matrix/client/r0/profile/@" . $username . ":" . $this->hs;
$handle = getCurlHandle($url); $handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
$res = $this->exec_curl_request($handle); $res = $this->exec_curl_request($handle);
return !(isset($res["errcode"]) && $res["errcode"] == "M_UNKNOWN"); return !(isset($res["errcode"]) && $res["errcode"] == "M_UNKNOWN");
} }
function getRegisterNonce() {
$url = "https://" . $this->hs . "/_matrix/client/r0/admin/register";
$handle = getCurlHandle($url);
try {
$response = $this->exec_curl_request($handle);
if (is_array($response) && isset($response["nonce"])) {
return $response["nonce"];
}
throw new Exception("INVALID_RESPONSE_FROM_SERVER");
} catch (Exception $e) {
if (strcmp("AUTHENTICATION_FAILED", $e->getMessage()) == 0) {
throw new Exception("WRONG_REGISTRATION_SHARED_SECRET");
} else {
throw $e;
}
}
}
function register($username, $password, $shared_secret) { function register($username, $password, $shared_secret) {
if (!$username) { if (!$username) {
error_log("no username provided"); error_log("no username provided");
} }
if (!$password) { if (!$password) {
error_log("no password provided"); error_log("no message to send");
} }
$nonce = $this->getRegisterNonce();
//TODO allow registering of admin. $mac = hash_hmac('sha1', $username, $shared_secret);
$hmac_content = $nonce . "\x00" . $username . "\x00" . $password . "\x00notadmin";
$mac = hash_hmac('sha1', $hmac_content, $shared_secret);
$data = array( $data = array(
"nonce" => $nonce,
"username" => $username, "username" => $username,
"password" => $password, "password" => $password,
"mac" => $mac, "mac" => $mac,
); );
$url = "https://" . $this->hs . "/_matrix/client/r0/admin/register"; $url = "https://" . $this->hs . "/_matrix/client/v2_alpha/register";
$handle = getCurlHandle($url); $handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($data));
try {
return $this->exec_curl_request($handle); return $this->exec_curl_request($handle);
} catch (Exception $e) {
if (strcmp("AUTHENTICATION_FAILED", $e->getMessage()) == 0) {
throw new Exception("WRONG_REGISTRATION_SHARED_SECRET");
} else {
throw $e;
}
}
} }
function exec_curl_request($handle) { function exec_curl_request($handle) {
@@ -147,7 +126,7 @@ class MatrixConnection {
$response = json_decode($response, true); $response = json_decode($response, true);
error_log("Request has failed with error {$response['error']}\n"); error_log("Request has failed with error {$response['error']}\n");
if ($http_code == 401) { if ($http_code == 401) {
throw new Exception("AUTHENTICATION_FAILED"); throw new Exception('Invalid access token provided');
} }
} else { } else {
$response = json_decode($response, true); $response = json_decode($response, true);
@@ -185,6 +164,7 @@ class MatrixMessage {
function get_object() { function get_object() {
return $this->message; return $this->message;
} }
} }
?> ?>

View File

@@ -1,55 +1,28 @@
# matrix-register-bot # matrix-register-bot
![state: alpha](https://img.shields.io/badge/state-alpha-yellowgreen.svg)
[![#matrix-register-bot:msg-net.de](https://img.shields.io/badge/matrix-%23matrix--register--bot%3Amsg--net.de-brightgreen.svg)](https://matrix.to/#/#matrix-register-bot:msg-net.de)
This bot provides a two-step-registration for matrix ([synapse](https://github.com/matrix-org/synapse)). This bot provides a two-step-registration for matrix.
This is done in several steps: This is done in several steps:
- potential new user registers on a bot-provided site - potential new user registers on a bot-provided side
- user has to verify its mail address
- bot sends a message to predefined room with a registration notification. - bot sends a message to predefined room with a registration notification.
- users in that room now can approve or decline the registration. - users in that room now can approve or decline the registration.
- When approved - When approved
- the bot creates short time credentials - the bot creates credentials
- sends them to the user - sends them to the user
- stores them encrypted in own databas or uses that as initial password for registration - stores them encrypted in own database
- provides that credentials to [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth#integrate) which has to be configured to query login.php
There are two operation modes available: 2nd step: Implement the other apis to integrade [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md)
- `operationMode=synapse`
- No adjustments on your running environment are required. This bot uses the the [Shared-Secret Registration of synapse](https://github.com/matrix-org/synapse/blob/master/docs/admin_api/register_api.rst) to register the users.
- `operationMode=local`:
- Bot handles user management. Therefore it stores the user-data and uses [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth#integrate) to authenticate the users.
- This way it is possible to set the display name of a user on first login (first- and lastname instead of username)
- The email address of the user can be used to implement third party lookup (requires [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/stores/rest.md))
- search for users you have not seen yet but are available on the server
## Requirements
- Working PHP environment with
- database connection provider \[one of sqlite, mysql, postgres\]
- curl extension
- mail capability to interact with the users (verification, approval (+ initial password), notifications)
- either via sendmail or with credentials
- [composer](https://getcomposer.org) installed
- [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth) when using `operationMode=local`
This bot takes care for user accounts. So it stores the credentials itself and provides ways to access them via matrix-synapse-rest-auth or mxisd.
## How to install ## How to install
``` - Copy `config.sample.php` to `config.php` and configure the bot as you can find there
git clone https://github.com/krombel/matrix-register-bot - Configure your webserver to publish the folder `public`.
cd matrix-register-bot The folder `internal` contains files that can be accessed by mxisd or matrix-synapse-rest-auth or else via a reverse proxy
composer install
cp config.sample.php config.php
editor config.php
```
- Configure your webserver to have the folder `public` accessible via web.
When running `operationMode=local`:
- Configure your webserver to provide the folder `internal` internally. This is only meant to be accessible by mxisd and matrix-synapse-rest-auth
- To integrate with [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth): - To integrate with [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth):
- `/_matrix-internal/identity/v1/check_credentials` should map to `internal/login.php` - `/_matrix-internal/identity/v1/check_credentials` should map to `internal/login.php`
- To integrate with [mxisd](https://github.com/kamax-io/mxisd): Have a look at [the docs of mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/stores/rest.md) and apply as follows: - To integrate with [mxisd](https://github.com/kamax-io/mxisd): Have a look at [the docs](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md) and apply as follows:
| Key | file which handles that | Description | | Key | file which handles that | Description |
@@ -60,25 +33,15 @@ When running `operationMode=local`:
| rest.endpoints.identity.bulk | internal/identity_bulk.php | Endpoint to query a list of 3PID | | rest.endpoints.identity.bulk | internal/identity_bulk.php | Endpoint to query a list of 3PID |
## Further notes: ## Implement usage of additional features:
### Use the ChangePasswortInterceptor:
### Security: Passwords from registration form are stored in clear text You need a reverse proxy which maps `/_matrix/client/r0/account/password` to `internal/intercept_change_password.php`.
Currently the passwords which are typed in while capturing the register request are stored in clear text.
The bot needs to access them to trigger a register request with correct credentials.
It is currently strongly recommended to set `"getPasswordOnRegistration" => false` in your config!
This leads to autocreating passwords which will then be send to the users directly without storing it.
### Use the ChangePasswortInterceptor (if `operationMode=local`)
To allow users to change their pasword you need a reverse proxy which maps `/_matrix/client/r0/account/password` to `internal/intercept_change_password.php`.
Here is an example for nginx: Here is an example for nginx:
``` ```
location /_matrix/client/r0/account/password { location /_matrix/client/r0/account/password {
proxy_pass http://localhost/mxbot/internal/intercept_change_password.php; proxy_pass http://localhost/mxbot/internal/intercept_change_password.php;
proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-For $remote_addr;
} }
``` ```
### The bot postpones some actions
There is a cron.php which implements retries and database cleanups (e.g. to remove a username claim)
For this run cron.php regularly with your system of choice.
A suggested interval is once per day

View File

@@ -1,15 +0,0 @@
{
"name": "krombel/matrix-register-bot",
"description": "Register-Bot which implements a 2-factor registration for synapse servers to take part on matrix-communication",
"type": "project",
"require": {
"phpmailer/phpmailer": "^6.0"
},
"license": "Apache-2.0",
"authors": [
{
"name": "Krombel",
"email": "krombel@krombel.de"
}
]
}

84
composer.lock generated
View File

@@ -1,84 +0,0 @@
{
"_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#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6d67203b6e9fc952ae681c538683a497",
"packages": [
{
"name": "phpmailer/phpmailer",
"version": "v6.0.6",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "8190d73eb5def11a43cfb020b7f36db65330698c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/8190d73eb5def11a43cfb020b7f36db65330698c",
"reference": "8190d73eb5def11a43cfb020b7f36db65330698c",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-filter": "*",
"php": ">=5.5.0"
},
"require-dev": {
"doctrine/annotations": "1.2.*",
"friendsofphp/php-cs-fixer": "^2.2",
"phpdocumentor/phpdocumentor": "2.*",
"phpunit/phpunit": "^4.8 || ^5.7",
"zendframework/zend-eventmanager": "3.0.*",
"zendframework/zend-i18n": "2.7.3",
"zendframework/zend-serializer": "2.7.*"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPMailer\\PHPMailer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1"
],
"authors": [
{
"name": "Jim Jagielski",
"email": "jimjag@gmail.com"
},
{
"name": "Marcus Bointon",
"email": "phpmailer@synchromedia.co.uk"
},
{
"name": "Andy Prevost",
"email": "codeworxtech@users.sourceforge.net"
},
{
"name": "Brent R. Matzelle"
}
],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"time": "2018-11-16T00:41:32+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

View File

@@ -5,18 +5,6 @@ $config = [
// Which e-mail-adresse shall the bot use to send e-mails? // Which e-mail-adresse shall the bot use to send e-mails?
"register_email" => 'register_bot@example.com', "register_email" => 'register_bot@example.com',
// which settings should be used to send via SMTP Gateway?
"smtp" => [
"host" => "localhost",
"port" => "25",
// use authentication?
"user" => "register@example.com",
"password" => "SecretEMailPassword",
// Use some encryption to SMTP-Server? [ssl, tls] or unset
"encryption" => False
],
// Where should the bot post registration requests to? // Where should the bot post registration requests to?
"register_room" => '$registerRoomID:example.com', "register_room" => '$registerRoomID:example.com',
@@ -31,10 +19,6 @@ $config = [
// - local (recommended; using a table in the database to store credentials; // - local (recommended; using a table in the database to store credentials;
// synapse has to be configured to use that) // synapse has to be configured to use that)
"operationMode" => "local", "operationMode" => "local",
// This setting is only required for operationMode = synapse
"registration_shared_secret" => "SOME_SECRET_KEY_FROM_HOMESERVER_CONFIG",
// When you want to collect the password on registration set this to true // When you want to collect the password on registration set this to true
// only evaluated when operationMode = local // only evaluated when operationMode = local
"getPasswordOnRegistration" => false, "getPasswordOnRegistration" => false,

View File

@@ -14,18 +14,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/config.php"); require_once("config.php");
require_once(__DIR__ . "/language.php"); require_once("mail_templates.php");
require_once(__DIR__ . "/mail_templates.php"); require_once("database.php");
require_once(__DIR__ . "/database.php");
$sql = "SELECT id, first_name, last_name, username, password, email," $sql = "SELECT id, first_name, last_name, username, email, state, note, verify_token, admin_token FROM registrations "
. " state, note, verify_token, admin_token "
. "FROM registrations "
. "WHERE state = " . RegisterState::PendingEmailSend . "WHERE state = " . RegisterState::PendingEmailSend
. " OR state = " . RegisterState::PendingAdminSend . " OR state = " . RegisterState::PendingAdminSend
. " OR state = " . RegisterState::PendingRegistration . " OR state = " . RegisterState::PendingRegistration
. " OR state = " . RegisterState::PendingSendRegistrationMail . ";"; . " OR state = " . RegisterState::PendingSendRegistrationMail
. " OR state = " . RegisterState::RegistrationDeclined
. " OR state = " . RegisterState::AllDone . ";";
foreach ($mx_db->query($sql) as $row) { foreach ($mx_db->query($sql) as $row) {
$first_name = $row["first_name"]; $first_name = $row["first_name"];
$last_name = $row["last_name"]; $last_name = $row["last_name"];
@@ -47,22 +46,16 @@ foreach ($mx_db->query($sql) as $row) {
} }
break; break;
case RegisterState::PendingAdminSend: case RegisterState::PendingAdminSend:
require_once(__DIR__ . "/MatrixConnection.php"); require_once("MatrixConnection.php");
$adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $row["admin_token"]; $adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $row["admin_token"];
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]); $mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$mxMsg = new MatrixMessage(); $mxMsg = new MatrixMessage();
$mxMsg->set_body(strtr($language["MSG_USER_WANTS_REGISTER"], [ $mxMsg->set_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:\r\n"
"@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username), . $row["note"] . "\r\n"
"@note" => $note, . "Zum Bearbeiten hier klicken:\r\n" . $adminUrl);
"@adminUrl" => $adminUrl $mxMsg->set_formatted_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:<br />"
])); . $row["note"] . "<br />"
if (isset($language["MSG_USER_WANTS_REGISTER_FORMATTED"])) { . "Zum Bearbeiten <a href=\"" . $adminUrl . "\">hier</a> klicken");
$mxMsg->set_formatted_body(strtr($language["MSG_USER_WANTS_REGISTER_FORMATTED"], [
"@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note,
"@adminUrl" => $adminUrl
]));
}
$mxMsg->set_type("m.text"); $mxMsg->set_type("m.text");
$response = $mxConn->send($config["register_room"], $mxMsg); $response = $mxConn->send($config["register_room"], $mxMsg);
@@ -76,29 +69,11 @@ foreach ($mx_db->query($sql) as $row) {
break; break;
case RegisterState::PendingRegistration: case RegisterState::PendingRegistration:
// Registration got accepted but registration failed // Registration got accepted but registration failed
switch ($config["operationMode"]) {
case "synapse": $password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["email"]);
// register with registration_shared_secret
// generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5));
$res = $mxConn->register($row["username"], $password, $config["registration_shared_secret"]);
if (!$res) {
// something went wrong while registering
$password = NULL;
}
break;
case "local":
// register by adding a user to the local database
$password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["password"], $row["email"]);
break;
default:
throw new Exception("Unknown operationMode");
}
if ($password != NULL) { if ($password != NULL) {
// send registration_success // send registration_success
$res = send_mail_registration_success( $res = send_mail_registration_success($config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]);
$config["homeserver"], strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username, $email, $username, $password, $config["howToURL"]
);
if ($res) { if ($res) {
$mx_db->setRegistrationStateById(RegisterState::AllDone, $row["id"]); $mx_db->setRegistrationStateById(RegisterState::AllDone, $row["id"]);
} else { } else {
@@ -108,9 +83,7 @@ foreach ($mx_db->query($sql) as $row) {
send_mail_registration_allowed_but_failed($config["homeserver"], $first_name . " " . $last_name, $email); send_mail_registration_allowed_but_failed($config["homeserver"], $first_name . " " . $last_name, $email);
$mxMsg = new MatrixMessage(); $mxMsg = new MatrixMessage();
$mxMsg->set_type("m.text"); $mxMsg->set_type("m.text");
$mxMsg->set_body(strtr($language["REGISTRATION_FAILED_FOR"], [ $mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . ".");
"@name" => strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username,
]));
$mxConn->send($config["register_room"], $mxMsg); $mxConn->send($config["register_room"], $mxMsg);
throw new Exception($language["REGISTRATION_FAILED"]); throw new Exception($language["REGISTRATION_FAILED"]);
} }
@@ -118,29 +91,14 @@ foreach ($mx_db->query($sql) as $row) {
case RegisterState::PendingSendRegistrationMail: case RegisterState::PendingSendRegistrationMail:
print ("Error: Unhandled state: PendingSendRegistrationMail for " . $first_name . " " . $last_name . " (" . $username . ")\n"); print ("Error: Unhandled state: PendingSendRegistrationMail for " . $first_name . " " . $last_name . " (" . $username . ")\n");
break; break;
case RegisterState::RegistrationDeclined:
case RegisterState::AllDone:
// do reqular cleanup
break;
} }
} catch (Exception $e) { } catch (Exception $e) {
print("Error while handling cron for " . $first_name . " " . $last_name . " (" . $username . ")\n"); print("Error while handling cron for " . $first_name . " " . $last_name . " (" . $username . ")\n");
print($e->getMessage()); print($e->getMessage());
} }
} }
try {
//cleanup: all finished entries older than one month
$timestamp = date('Y-m-d H:m:s', strtotime("-1 month"));
$mx_db->query("DELETE FROM registrations "
. "WHERE request_date < '$timestamp'"
. " AND (state = " . RegisterState::RegistrationDeclined
. " OR state = " . RegisterState::AllDone . " );"
);
//cleanup: all entries which are pending email registration older than two days
$timestamp = date('Y-m-d H:m:s', strtotime("-2 days"));
$mx_db->query("DELETE FROM registrations "
. "WHERE request_date < '$timestamp'"
. " AND state = " . RegisterState::PendingEmailVerify . ";"
);
} catch (Exception $e) {
print("Error while database cleanup\n");
print($e->getMessage());
}
?> ?>

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/config.php"); require_once("config.php");
if (!isset($config["databaseURI"])) { if (!isset($config["databaseURI"])) {
throw new Exception("malformed configuration: databaseURI not defined"); throw new Exception("malformed configuration: databaseURI not defined");
} }
@@ -78,7 +78,7 @@ class mxDatabase {
first_name TEXT, first_name TEXT,
last_name TEXT, last_name TEXT,
username TEXT, username TEXT,
password TEXT DEFAULT '', password_hash TEXT DEFAULT '',
note TEXT, note TEXT,
email TEXT, email TEXT,
verify_token TEXT, verify_token TEXT,
@@ -98,7 +98,7 @@ class mxDatabase {
)"); )");
// make sure the bot is allowed to login // make sure the bot is allowed to login
if (!$this->userRegistered("register_bot")) { if (!$this->userRegistered("register_bot")) {
$password = $this->addUser("Register", "Bot", "register_bot", NULL, $config["register_email"]); $password = $this->addUser("Register", "Bot", "register_bot", $config["register_email"]);
$config["register_password"] = $password; $config["register_password"] = $password;
$myfile = fopen(dirname(__FILE__) . "/config.json", "w"); $myfile = fopen(dirname(__FILE__) . "/config.json", "w");
fwrite($myfile, json_encode($config, JSON_PRETTY_PRINT)); fwrite($myfile, json_encode($config, JSON_PRETTY_PRINT));
@@ -184,7 +184,7 @@ class mxDatabase {
* *
* @return ["verify_token"] * @return ["verify_token"]
*/ */
function addRegistration($first_name, $last_name, $username, $password, $note, $email) { function addRegistration($first_name, $last_name, $username, $note, $email) {
if ($this->userPendingRegistrations($username)) { if ($this->userPendingRegistrations($username)) {
throw new Exception("USERNAME_PENDING_REGISTRATION"); throw new Exception("USERNAME_PENDING_REGISTRATION");
} }
@@ -196,9 +196,8 @@ class mxDatabase {
$admin_token = bin2hex(random_bytes(16)); $admin_token = bin2hex(random_bytes(16));
$this->db->exec("INSERT INTO registrations $this->db->exec("INSERT INTO registrations
(first_name, last_name, username, password, note, email, verify_token, admin_token) (first_name, last_name, username, note, email, verify_token, admin_token)
VALUES ('" . $first_name . "','" . $last_name . "','" VALUES ('" . $first_name . "','" . $last_name . "','" . $username . "','" . $note . "','"
. $username . "','" . $password . "','" . $note . "','"
. $email . "','" . $verify_token . "','" . $admin_token . "')"); . $email . "','" . $verify_token . "','" . $admin_token . "')");
return [ return [
@@ -218,7 +217,7 @@ class mxDatabase {
$res = $this->db->query($sql); $res = $this->db->query($sql);
if ($res->fetchColumn() > 0) { if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, username, password, note, email FROM registrations" $sql = "SELECT first_name, last_name, username, note, email FROM registrations"
. " WHERE admin_token = '" . $admin_token . "'" . " WHERE admin_token = '" . $admin_token . "'"
. " AND state = " . RegisterState::PendingAdminVerify . " AND state = " . RegisterState::PendingAdminVerify
. " LIMIT 1;"; . " LIMIT 1;";
@@ -283,16 +282,14 @@ class mxDatabase {
* NULL when failed * NULL when failed
* *
*/ */
function addUser($first_name, $last_name, $username, $password, $email) { function addUser($first_name, $last_name, $username, $email) {
// check if user already exists and abort in that case // check if user already exists and abort in that case
if ($this->userRegistered($username)) { if ($this->userRegistered($username)) {
return NULL; return NULL;
} }
if ($password == NULL) {
// generate a password with 10 characters // generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5)); $password = bin2hex(openssl_random_pseudo_bytes(5));
}
$password_hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]); $password_hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]);
$sql = "INSERT INTO logins (first_name, last_name, localpart, password_hash, email) VALUES " $sql = "INSERT INTO logins (first_name, last_name, localpart, password_hash, email) VALUES "

View File

@@ -30,13 +30,4 @@ function stripLocalpart($mxid) {
return $localpart; return $localpart;
} }
function getCurlHandle($url) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
return $handle;
}
?> ?>

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
$response = [ $response = [
"limited" => false, "limited" => false,
"result" => [], "result" => [],

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
$response = [ $response = [
"lookup" => [] "lookup" => []
]; ];

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
$response = new stdClass; $response = new stdClass;
try { try {
$inputJSON = file_get_contents('php://input'); $inputJSON = file_get_contents('php://input');

View File

@@ -44,14 +44,14 @@ try {
throw new Exception('"new_password" is not defined'); throw new Exception('"new_password" is not defined');
} }
require_once(__DIR__ . "/../helpers.php"); require_once("../helpers.php");
$localpart = stripLocalpart($input["auth"]["user"]); $localpart = stripLocalpart($input["auth"]["user"]);
if (empty($localpart)) { if (empty($localpart)) {
throw new Exception("localpart cannot be identified"); throw new Exception("localpart cannot be identified");
} }
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
if (!$mx_db->updatePassword( if (!$mx_db->updatePassword(
$localpart, $input["auth"]["password"], $input["new_password"] $localpart, $input["auth"]["password"], $input["new_password"]
)) { )) {

View File

@@ -20,7 +20,7 @@ $response = [
] ]
]; ];
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
abstract class LoginRequester { abstract class LoginRequester {
@@ -56,7 +56,7 @@ try {
// prefer the localpart attribute of mxisd. But in case of matrix-synapse-rest-auth // prefer the localpart attribute of mxisd. But in case of matrix-synapse-rest-auth
// we have to parse it on our own // we have to parse it on our own
if (empty($localpart)) { if (empty($localpart)) {
require_once(__DIR__ . "/../helpers.php"); require_once("../helpers.php");
$localpart = stripLocalpart($mxid); $localpart = stripLocalpart($mxid);
} }

View File

@@ -17,9 +17,6 @@
$language = array( $language = array(
"ACCEPT" => "Akzeptieren", "ACCEPT" => "Akzeptieren",
"DECLINE" => "Ablehnen", "DECLINE" => "Ablehnen",
"DECLINE_REASON" => "Grund für die Ablehnung",
"SUBMIT" => "Abschicken",
"MAKE_A_SELECTION" => "Treffe eine Auswahl",
"SUCCESS" => "Erfolgreich", "SUCCESS" => "Erfolgreich",
"FIRST_NAME" => "Vorname", "FIRST_NAME" => "Vorname",
"LAST_NAME" => "Nachname", "LAST_NAME" => "Nachname",
@@ -34,13 +31,10 @@ $language = array(
"UNKNOWN_SESSION" => "Sitzungstoken nicht vorhanden oder ungültig.", "UNKNOWN_SESSION" => "Sitzungstoken nicht vorhanden oder ungültig.",
"UNKNOWN_USERNAME" => "Nutzername fehlt", "UNKNOWN_USERNAME" => "Nutzername fehlt",
"UNKNOWN_TOKEN" => "Token ist unbekannt", "UNKNOWN_TOKEN" => "Token ist unbekannt",
"AUTHENTICATION_FAILED" => "Authentifizierung fehlgeschlagen", "USERNAME_LENGTH_INVALID" => "Entweder mehr als 20 oder weniger als 3 Zeichen für den Nutzernamen verwendet",
"WRONG_REGISTRATION_SHARED_SECRET" => "registration_shared_secret fehlerhaft",
"USERNAME_INVALID" => "Nutzername muss aus 3 bis 20 Kleinbuchstaben und Zahlen bestehen",
"USERNAME_NOT_ALNUM" => "Nutzername ist nicht alphanumerisch", "USERNAME_NOT_ALNUM" => "Nutzername ist nicht alphanumerisch",
"USERNAME_PENDING_REGISTRATION" => "Dieser Nutzername wurde bereits zur Registrierung vorgemerkt. Versuche es später noch einmal oder wähle einen anderen Nutzernamen", "USERNAME_PENDING_REGISTRATION" => "Dieser Nutzername wurde bereits zur Registrierung vorgemerkt. Versuche es später noch einmal oder wähle einen anderen Nutzernamen",
"USERNAME_REGISTERED" => "Dieser Nutzername wurde bereits registriert. Bitte wähle einen anderen Nutzernamen", "USERNAME_REGISTERED" => "Dieser Nutzername wurde bereits registriert. Bitte wähle einen anderen Nutzernamen",
"PASSWORD_NOT_PROVIDED" => "Ein oder beide Passwörter wurden nicht gesetzt",
"PASSWORD_NOT_MATCH" => "Passwörter stimmen nicht überein", "PASSWORD_NOT_MATCH" => "Passwörter stimmen nicht überein",
"NOTE_LENGTH_EXEEDED" => "Notiz ist länger als die erlaubten 50 Zeichen", "NOTE_LENGTH_EXEEDED" => "Notiz ist länger als die erlaubten 50 Zeichen",
"PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Notiz zu dir (max. 50 Zeichen)", "PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Notiz zu dir (max. 50 Zeichen)",

View File

@@ -1,5 +1,4 @@
<?php <?php
/** /**
* Copyright 2018 Matthias Kesler * Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +16,6 @@
$language = array( $language = array(
"ACCEPT" => "Accept", "ACCEPT" => "Accept",
"DECLINE" => "Decline", "DECLINE" => "Decline",
"DECLINE_REASON" => "Reason for declining",
"SUBMIT" => "Submit",
"MAKE_A_SELECTION" => "Make a selection",
"SUCCESS" => "Success", "SUCCESS" => "Success",
"FIRST_NAME" => "First name", "FIRST_NAME" => "First name",
"LAST_NAME" => "Last name", "LAST_NAME" => "Last name",
@@ -34,13 +30,10 @@ $language = array(
"UNKNOWN_SESSION" => "Session token not found of invalid.", "UNKNOWN_SESSION" => "Session token not found of invalid.",
"UNKNOWN_USERNAME" => "username unknown", "UNKNOWN_USERNAME" => "username unknown",
"UNKNOWN_TOKEN" => "Token is unknown", "UNKNOWN_TOKEN" => "Token is unknown",
"AUTHENTICATION_FAILED" => "Authentication failed", "USERNAME_LENGTH_INVALID" => "Username cpnsists pf more than 20 or less than 3 characters",
"WRONG_REGISTRATION_SHARED_SECRET" => "wrong registration_shared_secret",
"USERNAME_INVALID" => "Username has to consist of 3 to 20 small letters and numbers",
"USERNAME_NOT_ALNUM" => "Username is not alphanumeric", "USERNAME_NOT_ALNUM" => "Username is not alphanumeric",
"USERNAME_PENDING_REGISTRATION" => "This username is locked for registration. Try again later or try again with a different username", "USERNAME_PENDING_REGISTRATION" => "This username is locked for registration. Try again later or try again with a different username",
"USERNAME_REGISTERED" => "This username is already registered. Please try again with another username", "USERNAME_REGISTERED" => "This username is already registered. Please try again with another username",
"PASSWORD_NOT_PROVIDED" => "One or both passwords are not provided",
"PASSWORD_NOT_MATCH" => "passwords do not match", "PASSWORD_NOT_MATCH" => "passwords do not match",
"NOTE_LENGTH_EXEEDED" => "Note consists of more than 50 characters", "NOTE_LENGTH_EXEEDED" => "Note consists of more than 50 characters",
"PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Note about yourself (max. 50 characters)", "PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Note about yourself (max. 50 characters)",
@@ -60,8 +53,7 @@ $language = array(
"ADMIN_REGISTER_ACCEPTED_BODY" => "The registration request got accepted. The user got notified per email.", "ADMIN_REGISTER_ACCEPTED_BODY" => "The registration request got accepted. The user got notified per email.",
"ADMIN_REGISTER_DECLINED_BODY" => "The registration request got declined. The user got notified per email.", "ADMIN_REGISTER_DECLINED_BODY" => "The registration request got declined. The user got notified per email.",
"JUMP_TO_HOMEPAGE" => "To homepage", "JUMP_TO_HOMEPAGE" => "To homepage",
"TOPIC_PLEASE_REGISTER" => "Please register for @homeserver", "TOPIC_PLEASE_REGISTER" => "Please register for @homeserver<small>2-Step-Registration</small>",
"TOPIC_PLEASE_REGISTER_NOTE" => "2-Step-Registration",
"NOTE_FOR_REGISTRATION" => "@homeserver is a closed chat network where every user has to be confirmed.<br /> "NOTE_FOR_REGISTRATION" => "@homeserver is a closed chat network where every user has to be confirmed.<br />
You will get an email once sb. approved your registration. An initial password will be send to you afterwards. You will get an email once sb. approved your registration. An initial password will be send to you afterwards.
Please leave a note about yourself (that will only be shown to the admins).<br /> Please leave a note about yourself (that will only be shown to the admins).<br />

View File

@@ -1,5 +1,4 @@
<?php <?php
/** /**
* Copyright 2018 Matthias Kesler * Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,6 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
function send_mail($receiver, $subject, $body) {
include("config.php");
$headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers);
}
function send_mail_pending_verification($homeserver, $user, $receiver, $verify_url) { function send_mail_pending_verification($homeserver, $user, $receiver, $verify_url) {
$subject = "Bitte bestätige Registrierung auf $homeserver"; $subject = "Bitte bestätige Registrierung auf $homeserver";
$body = "Guten Tag " . $user . ", $body = "Guten Tag " . $user . ",
@@ -33,7 +39,7 @@ Danach ist eine Re-Registrierung mit deinem gewünschten Nutzernamen für andere
Vielen Dank für dein Verständnis. Vielen Dank für dein Verständnis.
Das Administratoren-Team von " . $homeserver; Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body );
} }
function send_mail_pending_approval($homeserver, $user, $receiver) { function send_mail_pending_approval($homeserver, $user, $receiver) {
@@ -47,7 +53,7 @@ Du bekommst eine weitere E-Mail, sobald deine Registrierung bestätigt oder able
Vielen Dank für dein Verständnis. Vielen Dank für dein Verständnis.
Das Administratoren-Team von " . $homeserver; Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body );
} }
function send_mail_registration_allowed_but_failed($homeserver, $user, $receiver) { function send_mail_registration_allowed_but_failed($homeserver, $user, $receiver) {
@@ -62,6 +68,7 @@ Wir melden uns, wenn die Registrierung erfolgreich war.
Das Administratoren-Team von " . $homeserver; Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body);
} }
function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) { function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) {
@@ -72,30 +79,30 @@ Deine Registrierungsanfrage wurde durch die Administratoren bestätigt.
Zum Anmelden kannst du folgende Zugangsdaten verwenden: Zum Anmelden kannst du folgende Zugangsdaten verwenden:
Nutzername: $username Nutzername: $username
Passwort: " . (empty($password) ? "wie selbst gesetzt": $password) . " Passwort: $password
Hinweis: Das Passwort kannst du aktuell über die App selbst ändern. Auch wenn das Passwort nirgends Hinweis: Das Passwort kannst du aktuell über die App selbst ändern. Auch wenn das Passwort nirgends
im Klartext gespeichert wird, kann jemand Zugriff auf diese Mail erlangen und so den Zugriff bekommen. im Klartext gespeichert wird, kann jemand Zugriff auf diese Mail erlangen und so den Zugriff bekommen.
"; ";
/* /*
Wichtig: Bitte ändere das Passwort direkt nach der Anmeldung. Wichtig: Bitte ändere das Passwort direkt nach der Anmeldung.
Es wird zwar von unserer Seite nicht gespeichert, doch fremde könnten Zugriff auf diese E-Mail Es wird zwar von unserer Seite nicht gespeichert, doch fremde könnten Zugriff auf diese E-Mail
erhalten und so deinen Account kompromittieren. erhalten und so deinen Account kompromittieren.
*/ */
if (!empty($howToURL)) { if (!empty($howToURL)) {
$body .= " $body .= "
Zu weiteren Hilfestellungen findest du hier eine Auflistung von verschiedenen Zu weiteren Hilfestellungen findest du hier eine Auflistung von verschiedenen
Anleitungen zu verschiedenen Clients: Anleitungen zu verschiedenen Clients:
$howToURL\n"; $howToURL\n";
} }
$body .= " $body .= "
Viel Spaß bei der Verwendung von $homeserver. Viel Spaß bei der Verwendung von $homeserver.
Bei Fragen findest du nach der Anmeldung ein paar Räume in denen du sie stellen kannst. Bei Fragen findest du nach der Anmeldung ein paar Räume in denen du sie stellen kannst.
Das Administratoren-Team von " . $homeserver; Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body);
}
}
function send_mail_registration_decline($homeserver, $user, $receiver, $reason) { function send_mail_registration_decline($homeserver, $user, $receiver, $reason) {
$subject = "Registrierung auf $homeserver abgelehnt"; $subject = "Registrierung auf $homeserver abgelehnt";
$body = "Guten Tag " . $user . ", $body = "Guten Tag " . $user . ",
@@ -112,7 +119,6 @@ Deine Registrierungsanfrage wurde durch die Administratoren abgelehnt.\n";
Wir hoffen, dass du dies akzeptieren kannst. Wir hoffen, dass du dies akzeptieren kannst.
Das Administratoren-Team von " . $homeserver; Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body );
} }
?> ?>

View File

@@ -1,5 +1,4 @@
<?php <?php
/** /**
* Copyright 2018 Matthias Kesler * Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,6 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
function send_mail($receiver, $subject, $body) {
include("config.php");
$headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers);
}
function send_mail_pending_verification($homeserver, $user, $receiver, $verify_url) { function send_mail_pending_verification($homeserver, $user, $receiver, $verify_url) {
$subject = "Pleast approve your registration request on $homeserver"; $subject = "Pleast approve your registration request on $homeserver";
$body = "Dear " . $user . ", $body = "Dear " . $user . ",
@@ -32,7 +38,7 @@ Others might take your username afterwards.
Thanks for your patience. Thanks for your patience.
The admin team of " . $homeserver; The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body );
} }
function send_mail_pending_approval($homeserver, $user, $receiver) { function send_mail_pending_approval($homeserver, $user, $receiver) {
@@ -46,7 +52,7 @@ You will get an email once they approve or decline your request.
Sincerely, Sincerely,
The admin team of " . $homeserver; The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body );
} }
function send_mail_registration_allowed_but_failed($homeserver, $user, $receiver) { function send_mail_registration_allowed_but_failed($homeserver, $user, $receiver) {
@@ -61,6 +67,7 @@ You will get another email with initial credentials once the registration got ha
The admin team of " . $homeserver; The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body);
} }
function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) { function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) {
@@ -71,25 +78,25 @@ Your registration request got verified by the admin team.
To log in you can use the following credentials:: To log in you can use the following credentials::
Username: $username Username: $username
Passwort: " . (empty($password) ? "as self-set": $password) . " Password: $password
Important: Please change your password as soon as possible after your first login. Important: Please change your password as soon as possible after your first login.
The password is not stored in clear text on the server but people could get access to this mail The password is not stored in clear text on the server but people could get access to this mail
and compromise your account. and compromise your account.
"; ";
if (!empty($howToURL)) { if (!empty($howToURL)) {
$body .= " $body .= "
You can find further help here:: You can find further help here::
$howToURL\n"; $howToURL\n";
} }
$body .= " $body .= "
Enjoy your usage of $homeserver. Enjoy your usage of $homeserver.
You can ask further questions inside of the chat system. You can ask further questions inside of the chat system.
The admin team of " . $homeserver; The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body);
}
}
function send_mail_registration_decline($homeserver, $user, $receiver, $reason) { function send_mail_registration_decline($homeserver, $user, $receiver, $reason) {
$subject = "Registration on $homeserver declined."; $subject = "Registration on $homeserver declined.";
$body = "Guten Tag " . $user . ", $body = "Guten Tag " . $user . ",
@@ -106,7 +113,6 @@ Your registration request got declined by the admin team.\n";
We hope that you can understand this reason. We hope that you can understand this reason.
The admin team of " . $homeserver; The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body); return send_mail($receiver, $subject, $body );
} }
?> ?>

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/config.php"); require_once("config.php");
$lang = $config["defaultLanguage"]; $lang = $config["defaultLanguage"];
if (isset($_GET['lang'])) { if (isset($_GET['lang'])) {
@@ -25,7 +25,7 @@ if (!file_exists($lang_file)) {
error_log("Translation for " . $lang . " not found. Fallback to 'de-de'"); error_log("Translation for " . $lang . " not found. Fallback to 'de-de'");
$lang = "de-de"; $lang = "de-de";
} }
$lang_file = __DIR__ . "/lang/lang." . $lang . ".php"; $lang_file = dirname(__FILE__) . "/lang/lang." . $lang . ".php";
require_once($lang_file); require_once($lang_file);
unset($lang_file); unset($lang_file);
?> ?>

View File

@@ -14,65 +14,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/config.php"); require_once("config.php");
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require_once(__DIR__ . "/vendor/autoload.php");
// standard mail implementation
function send_mail($receiver, $subject, $body) {
// somehow $config is not available when called again => reinit here
include(__DIR__ . "/config.php");
$mail = new PHPMailer(true);
try {
$mail->CharSet = 'utf-8'; // Enable utf-8 support for umlauts
if (is_array($config["smtp"])) {
$smtp_conf = $config["smtp"];
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = $smtp_conf["host"]; // Specify main and backup SMTP servers
$mail->Port = $smtp_conf["port"]; // TCP port to connect to
if (!empty($smtp_conf["user"])) {
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = $smtp_conf["user"]; // SMTP username
if (!empty($smtp_conf["password"])) {
$mail->Password = $smtp_conf["password"]; // SMTP password
}
}
if (!empty($smtp_conf["encryption"])) {
$mail->SMTPSecure = $smtp_conf["encryption"]; // Enable TLS encryption, `ssl` also accepted
}
} else {
// fallback to sendmail functionality (as before)
$mail->isSendmail();
}
//Recipients
$mail->setFrom($config["register_email"], 'Register Service');
$mail->addAddress($receiver);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->send();
return True;
} catch (Exception $e) {
error_log('Message could not be sent. Mailer Error: ' . $mail->ErrorInfo);
return False;
}
}
$lang = $config["defaultLanguage"]; $lang = $config["defaultLanguage"];
if (isset($_GET['lang'])) { if (isset($_GET['lang'])) {
$lang = filter_var($_GET['lang'], FILTER_SANITIZE_STRING); $lang = filter_var($_GET['lang'], FILTER_SANITIZE_STRING);
} }
$lang_file = __DIR__ . "/lang/mail." . $lang . ".php"; $lang_file = dirname(__FILE__) . "/lang/mail." . $lang . ".php";
if (!file_exists($lang_file)) { if (!file_exists($lang_file)) {
error_log("Mail templates for '" . $lang . "' not found. Fallback to 'de-de'"); error_log("Mail templates for '" . $lang . "' not found. Fallback to 'de-de'");
$lang = "de-de"; $lang = "de-de";
} }
$lang_file = __DIR__ . "/lang/mail." . $lang . ".php"; $lang_file = dirname(__FILE__) . "/lang/mail." . $lang . ".php";
require_once($lang_file); require_once($lang_file);
unset($lang_file); unset($lang_file);
?> ?>

View File

@@ -19,12 +19,12 @@ if (!isset($_SERVER['HTTPS'])) {
exit(); exit();
} }
require_once(__DIR__ . "/../language.php"); require_once "../language.php";
if (!file_exists(__DIR__ . "/../config.php")) { if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]); print($language["NO_CONFIGURATION"]);
exit(); exit();
} }
require_once(__DIR__ . "/../config.php"); require_once "../config.php";
// this values will not be used when using the register operation type // this values will not be used when using the register operation type
$storeFirstLastName = false; $storeFirstLastName = false;
@@ -46,23 +46,17 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
// token not present or invalid // token not present or invalid
throw new Exception("UNKNOWN_SESSION"); throw new Exception("UNKNOWN_SESSION");
} }
$username = filter_input(INPUT_POST, "username", FILTER_SANITIZE_STRING); if (!isset($_POST["username"])) {
if (empty($username)) {
throw new Exception("UNKNOWN_USERNAME"); throw new Exception("UNKNOWN_USERNAME");
} }
if (strlen($username) > 20 || strlen($username) < 3) { if (strlen($_POST["username"] > 20 || strlen($_POST["username"]) < 3)) {
throw new Exception("USERNAME_INVALID"); throw new Exception("USERNAME_LENGTH_INVALID");
} }
if (!ctype_alnum($username)) { if (ctype_alnum($_POST['username']) != true) {
throw new Exception("USERNAME_NOT_ALNUM"); throw new Exception("USERNAME_NOT_ALNUM");
} }
if (strcmp($username, strtolower($username)) !== 0) { if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"] &&
throw new Exception("USERNAME_INVALID"); $_POST["password"] != $_POST["password_confirm"]) {
}
if ($storePassword && (!isset($_POST["password"]) || !isset($_POST["password_confirm"]))) {
throw new Exception("PASSWORD_NOT_PROVIDED");
}
if ($storePassword && $_POST["password"] != $_POST["password_confirm"]) {
throw new Exception("PASSWORD_NOT_MATCH"); throw new Exception("PASSWORD_NOT_MATCH");
} }
if (isset($_POST["note"]) && strlen($_POST["note"]) > 50) { if (isset($_POST["note"]) && strlen($_POST["note"]) > 50) {
@@ -85,15 +79,15 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$first_name = $last_name = ""; $first_name = $last_name = "";
} }
$password = ""; $username = filter_var($_POST["username"], FILTER_SANITIZE_STRING);
if ($storePassword && isset($_POST["password"])) { if ($storePassword && isset($_POST["password"])) {
$password = filter_var($_POST["password"], FILTER_SANITIZE_STRING); $password = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
} }
$note = filter_var($_POST["note"], FILTER_SANITIZE_STRING); $note = filter_var($_POST["note"], FILTER_SANITIZE_STRING);
$email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL); $email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
$res = $mx_db->addRegistration($first_name, $last_name, $username, $password, $note, $email); $res = $mx_db->addRegistration($first_name, $last_name, $username, $note, $email);
if (!isset($res["verify_token"])) { if (!isset($res["verify_token"])) {
error_log("sth. went wrong. registration did not throw but admin_token not set"); error_log("sth. went wrong. registration did not throw but admin_token not set");
@@ -102,7 +96,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$verify_token = $res["verify_token"]; $verify_token = $res["verify_token"];
$verify_url = $config["webroot"] . "/verify.php?t=" . $verify_token; $verify_url = $config["webroot"] . "/verify.php?t=" . $verify_token;
require_once(__DIR__ . "/../mail_templates.php"); require_once "../mail_templates.php";
$success = send_mail_pending_verification( $success = send_mail_pending_verification(
$config["homeserver"], $storeFirstLastName ? $first_name . " " . $last_name : $username, $email, $verify_url); $config["homeserver"], $storeFirstLastName ? $first_name . " " . $last_name : $username, $email, $verify_url);
@@ -128,7 +122,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
} else { } else {
$_SESSION["token"] = bin2hex(random_bytes(16)); $_SESSION["token"] = bin2hex(random_bytes(16));
?> ?>
<title><?php echo strtr($language["TOPIC_PLEASE_REGISTER"], ["@homeserver" => $config["homeserver"]]); ?></title> <title><?php echo strtr($language["TOPIC_PLEASE_REGISTER"], [ "@homeserver" => $config["homeserver"] ]); ?></title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet"> <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet">
<style> <style>
body{ body{
@@ -152,14 +146,12 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4"> <div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title"><?php <h3 class="panel-title"><?php echo strtr($language["TOPIC_PLEASE_REGISTER"], [ "@homeserver" => $config["homeserver"] ])
echo strtr($language["TOPIC_PLEASE_REGISTER"], ["@homeserver" => $config["homeserver"]]) . "<small>" . $language["TOPIC_PLEASE_REGISTER_NOTE"] . "</small>"; ?></h3>
. "<small>" . $language["TOPIC_PLEASE_REGISTER_NOTE"] . "</small>";
?></h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form name="regForm" role="form" action="index.php" method="post"> <form name="regForm" role="form" action="index.php" method="post">
<?php if ($storeFirstLastName) { ?> <?php if ($storeFirstLastName) { ?>
<div class="row"> <div class="row">
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group"> <div class="form-group">
@@ -174,7 +166,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
</div> </div>
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
<div class="form-group"> <div class="form-group">
<input type="email" name="email" id="email" class="form-control input-sm" placeholder="<?php echo $language["EMAIL_ADDRESS"]; ?>" required> <input type="email" name="email" id="email" class="form-control input-sm" placeholder="<?php echo $language["EMAIL_ADDRESS"]; ?>" required>
@@ -188,7 +180,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<input type="text" name="username" id="username" class="form-control input-sm" <input type="text" name="username" id="username" class="form-control input-sm"
placeholder="<?php echo $language["USERNAME"]; ?>" pattern="[a-z1-9]{3,20}" required> placeholder="<?php echo $language["USERNAME"]; ?>" pattern="[a-z1-9]{3,20}" required>
</div> </div>
<?php if ($storePassword) { ?> <?php if ($storePassword) { ?>
<div class="row"> <div class="row">
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group"> <div class="form-group">
@@ -201,18 +193,16 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
</div> </div>
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
<input type="hidden" name="token" id="token" value="<?php echo $_SESSION["token"]; ?>"> <input type="hidden" name="token" id="token" value="<?php echo $_SESSION["token"]; ?>">
<input type="submit" value="<?php echo $language["REGISTER"]; ?>" class="btn btn-info btn-block"> <input type="submit" value="<?php echo $language["REGISTER"]; ?>" class="btn btn-info btn-block">
</form> </form>
<?php <?php if (isset($language["NOTE_FOR_REGISTRATION"])) {
if (isset($language["NOTE_FOR_REGISTRATION"])) {
echo "<p>" . $language["NOTE"] . ": <br />"; echo "<p>" . $language["NOTE"] . ": <br />";
echo strtr($language["NOTE_FOR_REGISTRATION"], ["@homeserver" => $config["homeserver"]]); echo strtr($language["NOTE_FOR_REGISTRATION"], [ "@homeserver" => $config["homeserver"] ]);
echo "</p>"; echo "</p>";
} } ?>
?>
</div> </div>
</div> </div>
</div> </div>
@@ -221,7 +211,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<script type="text/javascript"> <script type="text/javascript">
var user_name = document.getElementById("username"); var user_name = document.getElementById("username");
user_name.oninvalid = function (event) { user_name.oninvalid = function (event) {
event.target.setCustomValidity("<?php echo $language["USERNAME_INVALID"]; ?>"); event.target.setCustomValidity("<?php echo $language["USERNAME_LENGTH_INVALID"]; ?>");
} }
user_name.onkeyup = function (event) { user_name.onkeyup = function (event) {
event.target.setCustomValidity(""); event.target.setCustomValidity("");

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/../language.php"); require_once "../language.php";
if (!file_exists("../config.php")) { if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]); print($language["NO_CONFIGURATION"]);
exit(); exit();
} }
require_once(__DIR__ . "/../config.php"); require_once "../config.php";
require_once(__DIR__ . "/../mail_templates.php"); require_once "../mail_templates.php";
// enforce admin via https // enforce admin via https
if (!isset($_SERVER['HTTPS'])) { if (!isset($_SERVER['HTTPS'])) {
@@ -38,7 +38,7 @@ try {
} }
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING); $token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
$user = $mx_db->getUserForVerify($token); $user = $mx_db->getUserForVerify($token);
if ($user == NULL) { if ($user == NULL) {
@@ -51,21 +51,18 @@ try {
$email = $user["email"]; $email = $user["email"];
$admin_token = $user["admin_token"]; $admin_token = $user["admin_token"];
// we have 2 cases: first and last name or just the username require_once("../MatrixConnection.php");
$call_name = strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username;
require_once(__DIR__ . "/../MatrixConnection.php");
$adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $admin_token; $adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $admin_token;
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]); $mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$mxMsg = new MatrixMessage(); $mxMsg = new MatrixMessage();
$mxMsg->set_body(strtr($language["MSG_USER_WANTS_REGISTER"], [ $mxMsg->set_body(strtr($language["MSG_USER_WANTS_REGISTER"], [
"@name" => $call_name, "@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note, "@note" => $note,
"@adminUrl" => $adminUrl "@adminUrl" => $adminUrl
])); ]));
if (isset($language["MSG_USER_WANTS_REGISTER_FORMATTED"])) { if (isset($language["MSG_USER_WANTS_REGISTER_FORMATTED"])) {
$mxMsg->set_formatted_body(strtr($language["MSG_USER_WANTS_REGISTER_FORMATTED"], [ $mxMsg->set_formatted_body(strtr($language["MSG_USER_WANTS_REGISTER_FORMATTED"], [
"@name" => $call_name, "@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note, "@note" => $note,
"@adminUrl" => $adminUrl "@adminUrl" => $adminUrl
])); ]));
@@ -79,7 +76,7 @@ try {
$mx_db->setRegistrationStateVerify( $mx_db->setRegistrationStateVerify(
($response ? RegisterState::PendingAdminVerify : RegisterState::PendingAdminSend), $token); ($response ? RegisterState::PendingAdminVerify : RegisterState::PendingAdminSend), $token);
send_mail_pending_approval($config["homeserver"], $call_name, $email); send_mail_pending_approval($config["homeserver"], $first_name . " " . $last_name, $email);
print("<title>" . $language["VERIFICATION_SUCEEDED"] . "</title>"); print("<title>" . $language["VERIFICATION_SUCEEDED"] . "</title>");
print("</head><body>"); print("</head><body>");

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
require_once(__DIR__ . "/../language.php"); require_once "../language.php";
if (!file_exists("../config.php")) { if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]); print($language["NO_CONFIGURATION"]);
exit(); exit();
} }
require_once(__DIR__ . "/../config.php"); require_once "../config.php";
require_once(__DIR__ . "/../mail_templates.php"); require_once "../mail_templates.php";
// enforce admin via https // enforce admin via https
if (!isset($_SERVER['HTTPS'])) { if (!isset($_SERVER['HTTPS'])) {
@@ -33,19 +33,23 @@ try {
if ($_SERVER["REQUEST_METHOD"] != "GET") { if ($_SERVER["REQUEST_METHOD"] != "GET") {
throw new Exception("Method not allowed"); throw new Exception("Method not allowed");
} }
$token = filter_input(INPUT_GET, "t", FILTER_SANITIZE_STRING); if (!isset($_GET["t"])) {
if (empty($token)) {
throw new Exception("UNKNOWN_TOKEN"); throw new Exception("UNKNOWN_TOKEN");
} }
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
require_once(__DIR__ . "/../database.php"); require_once("../database.php");
$param_action = filter_input(INPUT_GET, "d", FILTER_SANITIZE_STRING); $action = NULL;
if ($param_action == "allow") { if (isset($_GET["allow"])) {
$action = RegisterState::RegistrationAccepted; $action = RegisterState::RegistrationAccepted;
} elseif ($param_action == "deny") { }
$decline_reason = NULL;
if (isset($_GET["deny"])) {
$action = RegisterState::RegistrationDeclined; $action = RegisterState::RegistrationDeclined;
$decline_reason = filter_input(INPUT_GET, "decline_reason", FILTER_SANITIZE_STRING); if (isset($_GET["reason"])) {
$decline_reason = filter_var($_GET["reason"], FILTER_SANITIZE_STRING);
}
} }
$user = $mx_db->getUserForApproval($token); $user = $mx_db->getUserForApproval($token);
@@ -56,9 +60,6 @@ try {
$first_name = $user["first_name"]; $first_name = $user["first_name"];
$last_name = $user["last_name"]; $last_name = $user["last_name"];
$username = $user["username"]; $username = $user["username"];
// we have 2 cases: first and last name or just the username
$call_name = strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username;
$note = $user["note"]; $note = $user["note"];
$email = $user["email"]; $email = $user["email"];
@@ -66,44 +67,15 @@ try {
$mx_db->setRegistrationStateAdmin(RegisterState::PendingRegistration, $token); $mx_db->setRegistrationStateAdmin(RegisterState::PendingRegistration, $token);
// register user // register user
require_once(__DIR__ . "/../MatrixConnection.php"); require_once("../MatrixConnection.php");
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]); $mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$password = NULL; // generate a password with 8 characters
$use_db_password = (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"]); $password = $mx_db->addUser($first_name, $last_name, $username, $email);
if ($use_db_password && isset($user["password"]) && strlen($user["password"]) > 0) {
$password = $user["password"];
} else {
$use_db_password = false;
// generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5));
}
switch ($config["operationMode"]) {
case "synapse":
// register with registration_shared_secret
$res = $mxConn->register($username, $password, $config["registration_shared_secret"]);
if (!$res) {
// something went wrong while registering
$password = NULL;
}
break;
case "local":
// register by adding a user to the local database
$password = $mx_db->addUser($first_name, $last_name, $username, $password, $email);
break;
default:
throw new Exception("Unknown operationMode");
}
if ($password != NULL) { if ($password != NULL) {
// send registration_success // send registration_success
$res = send_mail_registration_success( $res = send_mail_registration_success(
$config["homeserver"], $config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]
$call_name,
$email,
$username,
// only send password when auto-created
($use_db_password ? NULL : $password),
$config["howToURL"]
); );
if ($res) { if ($res) {
$mx_db->setRegistrationStateAdmin(RegisterState::AllDone, $token); $mx_db->setRegistrationStateAdmin(RegisterState::AllDone, $token);
@@ -111,11 +83,11 @@ try {
$mx_db->setRegistrationStateAdmin(RegisterState::PendingSendRegistrationMail, $token); $mx_db->setRegistrationStateAdmin(RegisterState::PendingSendRegistrationMail, $token);
} }
} else { } else {
send_mail_registration_allowed_but_failed($config["homeserver"], $call_name, $email); send_mail_registration_allowed_but_failed($config["homeserver"], $first_name . " " . $last_name, $email);
$mxMsg = new MatrixMessage(); $mxMsg = new MatrixMessage();
$mxMsg->set_type("m.text"); $mxMsg->set_type("m.text");
$mxMsg->set_body(strtr($language["REGISTRATION_FAILED_FOR"], [ $mxMsg->set_body(strtr($language["REGISTRATION_FAILED_FOR"], [
"@name" => $call_name, "@name" => strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username,
])); ]));
$mxConn->send($config["register_room"], $mxMsg); $mxConn->send($config["register_room"], $mxMsg);
throw new Exception("REGISTRATION_FAILED"); throw new Exception("REGISTRATION_FAILED");
@@ -128,13 +100,14 @@ try {
} elseif ($action == RegisterState::RegistrationDeclined) { } elseif ($action == RegisterState::RegistrationDeclined) {
$mx_db->setRegistrationStateAdmin(RegisterState::RegistrationDeclined, $token); $mx_db->setRegistrationStateAdmin(RegisterState::RegistrationDeclined, $token);
send_mail_registration_decline( send_mail_registration_decline(
$config["homeserver"], $call_name, $email, $decline_reason $config["homeserver"], strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username, $email, $decline_reason
); );
print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>"); print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>");
print("</head><body>"); print("</head><body>");
print("<h1>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</h1>"); print("<h1>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</h1>");
print("<p>" . $language["ADMIN_REGISTER_DECLINED_BODY"] . "</p>"); print("<p>" . $language["ADMIN_REGISTER_DECLINED_BODY"] . "</p>");
} else { } else {
print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>"); print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>");
?> ?>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet"> <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet">
@@ -163,9 +136,8 @@ try {
<h3 class="panel-title"><?php echo $language["ADMIN_VERIFY_SITE_TITLE"]; ?></h3> <h3 class="panel-title"><?php echo $language["ADMIN_VERIFY_SITE_TITLE"]; ?></h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form name="appForm" role="form" onsubmit="return submitForm()" action="verify_admin.php" method="GET"> <form name="appForm" role="form" action="verify_admin.php" method="GET">
<?php <?php if (isset($config["operationMode"]) && $config["operationMode"] === "local") {
if (isset($config["operationMode"]) && $config["operationMode"] === "local") {
// this values will not be used when using the register operation type // this values will not be used when using the register operation type
?> ?>
<div class="row"> <div class="row">
@@ -182,7 +154,7 @@ try {
</div> </div>
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
<div class="form-group"> <div class="form-group">
<input type="text" id="note" class="form-control input-sm" value="<?php echo $note; ?>" disabled=true> <input type="text" id="note" class="form-control input-sm" value="<?php echo $note; ?>" disabled=true>
</div> </div>
@@ -191,16 +163,9 @@ try {
<input type="text" id="username" class="form-control input-sm" <input type="text" id="username" class="form-control input-sm"
value="<?php echo $username; ?>" disabled=true> value="<?php echo $username; ?>" disabled=true>
</div> </div>
<div class="form-group">
<input type="hidden" name="decline_reason" class="form-control input-sm"
placeholder="<?php echo $language["DECLINE_REASON"]; ?>">
</div>
<input type="hidden" name="t" id="token" value="<?php echo $token; ?>"> <input type="hidden" name="t" id="token" value="<?php echo $token; ?>">
<div class="form-group"> <input type="submit" name="allow" value="<?php echo $language["ACCEPT"]; ?>" class="btn btn-info btn-block">
<input type="radio" name="d" value="allow"><?php echo $language["ACCEPT"]; ?> <input type="submit" name="deny" value="<?php echo $language["DECLINE"]; ?>" class="btn btn-info btn-block">
<input type="radio" name="d" value="deny"><?php echo $language["DECLINE"]; ?>
</div>
<input type="submit" value="<?php echo $language["SUBMIT"]; ?>" class="btn btn-info btn-block">
</form> </form>
</div> </div>
</div> </div>
@@ -208,30 +173,7 @@ try {
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var rad = document.appForm.d;
function isSelected() {
for (var i=0; i<rad.length; i++)
if (rad[i].checked)
return true;
return false;
}
function submitForm() {
if (isSelected()) {
return true;
}
alert("<?php echo $language["MAKE_A_SELECTION"];?>");
return false;
}
for(var i = 0; i < rad.length; i++) {
rad[i].onclick = function() {
if (this.value === "deny") {
document.appForm.decline_reason.type = "text";
} else {
document.appForm.decline_reason.type = "hidden";
}
};
}
</script>
<?php <?php
} // else - no action provided } // else - no action provided
} catch (Exception $e) { } catch (Exception $e) {
@@ -246,5 +188,5 @@ try {
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>"); print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>");
} }
?> ?>
</body> < /body>
</html> </html>