1 Commits

Author SHA1 Message Date
ae83ea1404 further implementing of multilanguage 2018-03-26 23:13:26 +02:00
20 changed files with 1109 additions and 1372 deletions

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class MatrixConnection {
class MatrixConnection
{
private $hs;
private $at;
@@ -34,7 +33,7 @@ class MatrixConnection {
if (!$message) {
error_log("no message to send");
return false;
} elseif (is_array($message)) {
} elseif(is_array($message)) {
$send_message = $message;
} elseif ($message instanceof MatrixMessage) {
$send_message = $message->get_object();
@@ -43,8 +42,8 @@ class MatrixConnection {
return false;
}
$url = "https://" . $this->hs . "/_matrix/client/r0/rooms/"
. urlencode($room_id) . "/send/m.room.message?access_token=" . $this->at;
$url="https://".$this->hs."/_matrix/client/r0/rooms/"
. urlencode($room_id) ."/send/m.room.message?access_token=".$this->at;
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
@@ -66,10 +65,10 @@ class MatrixConnection {
function hasUser($username) {
if (!$username) {
throw new Exception("no user given to lookup");
throw new Exception ("no user given to lookup");
}
$url = "https://" . $this->hs . "/_matrix/client/r0/profile/@" . $username . ":" . $this->hs;
$url = "https://".$this->hs."/_matrix/client/r0/profile/@" . $username . ":" . $this->hs;
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
@@ -95,7 +94,7 @@ class MatrixConnection {
"password" => $password,
"mac" => $mac,
);
$url = "https://" . $this->hs . "/_matrix/client/v2_alpha/register";
$url = "https://".$this->hs."/_matrix/client/v2_alpha/register";
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
@@ -103,19 +102,12 @@ class MatrixConnection {
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($data));
try {
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) {
$response = curl_exec($handle);
if ($response === false) {
$errno = curl_errno($handle);
$error = curl_error($handle);
@@ -123,6 +115,7 @@ class MatrixConnection {
curl_close($handle);
return false;
}
$http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE));
curl_close($handle);
@@ -134,18 +127,18 @@ class MatrixConnection {
$response = json_decode($response, true);
error_log("Request has failed with error {$response['error']}\n");
if ($http_code == 401) {
throw new Exception("AUTHENTICATION_FAILED");
throw new Exception('Invalid access token provided');
}
} else {
$response = json_decode($response, true);
}
return $response;
}
}
class MatrixMessage {
class MatrixMessage
{
private $message;
function __construct() {
@@ -164,7 +157,7 @@ class MatrixMessage {
$this->message["body"] = $body;
}
function set_formatted_body($fbody, $format = "org.matrix.custom.html") {
function set_formatted_body($fbody, $format="org.matrix.custom.html") {
$this->message["formatted_body"] = $fbody;
$this->message["format"] = $format;
}
@@ -172,7 +165,5 @@ class MatrixMessage {
function get_object() {
return $this->message;
}
}
?>

View File

@@ -1,45 +1,27 @@
# 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:
- potential new user registers on a bot-provided site
- user has to verify its mail address
- potential new user registers on a bot-provided side
- bot sends a message to predefined room with a registration notification.
- users in that room now can approve or decline the registration.
- When approved
- the bot creates short time credentials
- the bot creates credentials
- 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
To configure synapse so that the users can login that were created via this bot you can either
- set `operationMode=synapse` so the bot uses the register api to push the new users to synapse or
- integrate it via [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth#integrate) by configuring your system to point at `internal/login.php`.
When using `operationMode=local` you can have the following benefits (some require [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/stores/rest.md))
- Automatically set the display name based on first and last name on first login
- Use the 3PID lookup for other users (only email)
- Search for users that you have not seen yet
## Requirements
- Working PHP environment with
- database connection provider \[one of sqlite, mysql, postgres\]
- curl extension to notify admins and register users (in `operationMode=synapse`)
- mail capability to interact with the users (Verification, Approval (+ initial password), Notifications)
- matrix-synapse-rest-auth when using `operationMode=local`
- some PHP capable webserver which makes the folder `public` accessible to the public and propably `internal` for server-internal access
2nd step: Implement the other apis to integrade [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md)
## How to install
- Copy `config.sample.php` to `config.php` and configure the bot as you can find there
- Configure your webserver to have the folder `public` accessible via web.
The folder `internal` contains files that only provide API access. They can be accessed by mxisd or matrix-synapse-rest-auth
- To integrate with [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth):
- Configure your webserver to publish the folder `public` and configure.
The folder `internal` contains files that can be accessed by mxisd or matrix-synapse-rest-auth
- To integrate with matrix-synapse-rest-auth:
- `/_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: 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 |
@@ -48,26 +30,3 @@ When using `operationMode=local` you can have the following benefits (some requi
| rest.endpoints.directory | internal/directory_search.php | Search for users by arbitrary input |
| rest.endpoints.identity.single | internal/identity_single.php | Endpoint to query a single 3PID |
| rest.endpoints.identity.bulk | internal/identity_bulk.php | Endpoint to query a list of 3PID |
## Further notes:
### Security: Passwords from registration form are stored in clear text
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:
```
location /_matrix/client/r0/account/password {
proxy_pass http://localhost/mxbot/internal/intercept_change_password.php;
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.

View File

@@ -14,26 +14,16 @@ $config = [
// optional: Do you have a place where howTo's are located? If not leave this value out
"howToURL" => "https://my-url-for-storing-howTos.net",
// set the mode of operation. Basically this defines where the data is stored:
// - synapse (using the register endpoint - so no further auth config necessary
// - local (recommended; using a table in the database to store credentials;
// synapse has to be configured to use that)
"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
// only evaluated when operationMode = local
"getPasswordOnRegistration" => false,
// default language: one of [ en-gb | de-de ]
"defaultLanguage" => "en-gb",
// to define where the data should be stored:
"databaseURI" => "sqlite:" . dirname(__FILE__) . "/db_file.sqlite",
// credentials for sqlite not used
"databaseUser" => "dbUser123",
"databasePass" => "secretPassword",
]
// default language: one of [ en-gb | de-de ]
"defaultLanguage" => "en-gb"
]
?>

102
cron.php
View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,18 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
require_once(__DIR__ . "/language.php");
require_once(__DIR__ . "/mail_templates.php");
require_once(__DIR__ . "/database.php");
require_once("config.php");
require_once("mail_templates.php");
require_once("database.php");
$sql = "SELECT id, first_name, last_name, username, password, email,"
. " state, note, verify_token, admin_token "
. "FROM registrations "
. "WHERE state = " . RegisterState::PendingEmailSend
. " OR state = " . RegisterState::PendingAdminSend
. " OR state = " . RegisterState::PendingRegistration
. " OR state = " . RegisterState::PendingSendRegistrationMail . ";";
$sql = "SELECT id, first_name, last_name, username, email, state, note, verify_token, admin_token FROM registrations "
."WHERE state = ". RegisterState::PendingEmailSend
. " OR state = " . RegisterState::PendingAdminSend
. " OR state = " . RegisterState::PendingRegistration
. " OR state = " . RegisterState::PendingSendRegistrationMail
. " OR state = " . RegisterState::RegistrationDeclined
. " OR state = " . RegisterState::AllDone . ";";
foreach ($mx_db->query($sql) as $row) {
$first_name = $row["first_name"];
$last_name = $row["last_name"];
@@ -38,31 +36,28 @@ foreach ($mx_db->query($sql) as $row) {
case RegisterState::PendingEmailSend:
$verify_url = $config["webroot"] . "/verify.php?t=" . $row["verify_token"];
$success = send_mail_pending_verification(
$config["homeserver"], $row["first_name"] . " " . $row["last_name"], $row["email"], $verify_url);
$config["homeserver"],
$row["first_name"] . " " . $row["last_name"],
$row["email"],
$verify_url);
if ($success) {
$mx_db->setRegistrationStateById(RegisterState::PendingEmailVerify, $row["id"]);
} else {
throw new Exception("Could not send mail to " . $row["first_name"] . " " . $row["last_name"] . "(" . $row["id"] . ")");
throw new Exception("Could not send mail to ".$row["first_name"]." ".$row["last_name"]."(".$row["id"].")");
}
break;
case RegisterState::PendingAdminSend:
require_once(__DIR__ . "/MatrixConnection.php");
require_once("MatrixConnection.php");
$adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $row["admin_token"];
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$mxMsg = new MatrixMessage();
$mxMsg->set_body(strtr($language["MSG_USER_WANTS_REGISTER"], [
"@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note,
"@adminUrl" => $adminUrl
]));
if (isset($language["MSG_USER_WANTS_REGISTER_FORMATTED"])) {
$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_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:\r\n"
. $row["note"] . "\r\n"
. "Zum Bearbeiten hier klicken:\r\n" . $adminUrl);
$mxMsg->set_formatted_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:<br />"
. $row["note"] . "<br />"
. "Zum Bearbeiten <a href=\"". $adminUrl . "\">hier</a> klicken");
$mxMsg->set_type("m.text");
$response = $mxConn->send($config["register_room"], $mxMsg);
@@ -71,34 +66,16 @@ foreach ($mx_db->query($sql) as $row) {
send_mail_pending_approval($config["homeserver"], $first_name . " " . $last_name, $email);
} else {
throw new Exception("Could not send notification for " . $row["first_name"] . " " . $row["last_name"] . "(" . $row["id"] . ") to admins.");
throw new Exception("Could not send notification for ".$row["first_name"]." ".$row["last_name"]."(".$row["id"].") to admins.");
}
break;
case RegisterState::PendingRegistration:
// Registration got accepted but registration failed
switch ($config["operationMode"]) {
case "synapse":
// 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");
}
$password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["email"]);
if ($password != NULL) {
// send registration_success
$res = send_mail_registration_success(
$config["homeserver"], strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username, $email, $username, $password, $config["howToURL"]
);
$res = send_mail_registration_success($config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]);
if ($res) {
$mx_db->setRegistrationStateById(RegisterState::AllDone, $row["id"]);
} else {
@@ -108,9 +85,7 @@ foreach ($mx_db->query($sql) as $row) {
send_mail_registration_allowed_but_failed($config["homeserver"], $first_name . " " . $last_name, $email);
$mxMsg = new MatrixMessage();
$mxMsg->set_type("m.text");
$mxMsg->set_body(strtr($language["REGISTRATION_FAILED_FOR"], [
"@name" => strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username,
]));
$mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . ".");
$mxConn->send($config["register_room"], $mxMsg);
throw new Exception($language["REGISTRATION_FAILED"]);
}
@@ -118,29 +93,14 @@ foreach ($mx_db->query($sql) as $row) {
case RegisterState::PendingSendRegistrationMail:
print ("Error: Unhandled state: PendingSendRegistrationMail for " . $first_name . " " . $last_name . " (" . $username . ")\n");
break;
case RegisterState::RegistrationDeclined:
case RegisterState::AllDone:
// do reqular cleanup
break;
}
} catch (Exception $e) {
print("Error while handling cron for " . $first_name . " " . $last_name . " (" . $username . ")\n");
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

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
require_once("config.php");
if (!isset($config["databaseURI"])) {
throw new Exception("malformed configuration: databaseURI not defined");
throw new Exception ("malformed configuration: databaseURI not defined");
}
abstract class RegisterState {
abstract class RegisterState
{
// Sending an E-Mail failed in the first attempt. Will retry later
const PendingEmailSend = 0;
// User got a mail. We wait for it to verfiy
@@ -31,19 +30,21 @@ abstract class RegisterState {
const PendingAdminVerify = 6;
// Registration failed on first attempt. Will retry
const PendingRegistration = 7;
// in this case we have to reset the password of the user (or should we store it for this case?)
const PendingSendRegistrationMail = 8;
// State to allow persisting in the database although an admin declined it.
// Will be removed regularly
const RegistrationAccepted = 7;
const RegistrationDeclined = 13;
// User got successfully registered. Will be cleaned up later
const AllDone = 100;
}
class mxDatabase {
class mxDatabase
{
private $db = NULL;
/**
@@ -78,7 +79,7 @@ class mxDatabase {
first_name TEXT,
last_name TEXT,
username TEXT,
password TEXT DEFAULT '',
password_hash TEXT DEFAULT '',
note TEXT,
email TEXT,
verify_token TEXT,
@@ -98,7 +99,7 @@ class mxDatabase {
)");
// make sure the bot is allowed to login
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;
$myfile = fopen(dirname(__FILE__) . "/config.json", "w");
fwrite($myfile, json_encode($config, JSON_PRETTY_PRINT));
@@ -163,7 +164,6 @@ class mxDatabase {
}
return false;
}
function userRegistered($username) {
$sql = "SELECT COUNT(*) FROM logins WHERE localpart = '" . $username . "' LIMIT 1;";
$res = $this->db->query($sql);
@@ -184,7 +184,7 @@ class mxDatabase {
*
* @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)) {
throw new Exception("USERNAME_PENDING_REGISTRATION");
}
@@ -196,13 +196,12 @@ class mxDatabase {
$admin_token = bin2hex(random_bytes(16));
$this->db->exec("INSERT INTO registrations
(first_name, last_name, username, password, note, email, verify_token, admin_token)
VALUES ('" . $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 . "','" . $username . "','" . $note . "','"
. $email."','" .$verify_token."','" .$admin_token."')");
return [
"verify_token" => $verify_token,
"verify_token"=> $verify_token,
];
}
@@ -216,9 +215,10 @@ class mxDatabase {
$sql = "SELECT COUNT(*) FROM registrations WHERE admin_token = '" . $admin_token . "'"
. " AND state = " . RegisterState::PendingAdminVerify . " LIMIT 1;";
$res = $this->db->query($sql);
$first_name = NULL; $last_name = NULL; $username = NULL; $note = NULL; $email = NULL;
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 . "'"
. " AND state = " . RegisterState::PendingAdminVerify
. " LIMIT 1;";
@@ -240,9 +240,10 @@ class mxDatabase {
$sql = "SELECT COUNT(*) FROM registrations WHERE verify_token = '" . $verify_token . "'"
. " AND state = " . RegisterState::PendingEmailVerify . " LIMIT 1;";
$res = $this->db->query($sql);
$first_name = NULL; $last_name = NULL; $username = NULL; $note = NULL; $email = NULL;
if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, note, email, username, admin_token FROM registrations "
$sql = "SELECT first_name, last_name, note, email, admin_token FROM registrations "
. " WHERE verify_token = '" . $verify_token . "'"
. " AND state = " . RegisterState::PendingEmailVerify . " LIMIT 1;";
foreach ($this->db->query($sql) as $row) {
@@ -283,20 +284,18 @@ class mxDatabase {
* 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
if ($this->userRegistered($username)) {
return NULL;
}
if ($password == NULL) {
// generate a password with 10 characters
$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 "
. "('" . $first_name . "','" . $last_name . "','" . $username . "','"
. "('" . $first_name."','" . $last_name . "','" . $username . "','"
. $password_hash . "','" . $email . "');";
if ($this->db->exec($sql)) {
@@ -308,11 +307,11 @@ class mxDatabase {
function updatePassword($localpart, $old_password, $new_password) {
$user = $this->getUserForLogin($localpart, $old_password);
if ($user == NULL) {
throw new Exception("user with that credentials not found");
throw new Exception ("user with that credentials not found");
}
// The credentials were fine. So now set the new password
$password_hash = password_hash($new_password, PASSWORD_BCRYPT, ["cost" => 12]);
$password_hash = password_hash($new_password, PASSWORD_BCRYPT, ["cost"=>12]);
$sql = "UPDATE logins SET password_hash = '" . $password_hash . "'"
. "WHERE localpart = '" . $localpart . "'";
@@ -362,7 +361,6 @@ class mxDatabase {
}
return $result;
}
}
if (!isset($mx_db)) {

View File

@@ -1,30 +1,15 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function stripLocalpart($mxid) {
$localpart = NULL;
if (!empty($mxid)) {
// A mxid would start with an @ so we start at the 2. position
$sepPos = strpos($mxid, ':', 1);
$sepPos = strpos($mxid,':', 1);
if ($sepPos === false) {
// : not found. Assume mxid is localpart
// TODO: further checks
$localpart = $mxid;
} else {
$localpart = substr($mxid, 1, strpos($mxid, ':') - 1);
$localpart = substr($mxid, 1, strpos($mxid,':') - 1 );
}
}
return $localpart;

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../database.php");
$response = [
require_once("../database.php");
$response=[
"limited" => false,
"result" => [],
];
@@ -40,11 +39,12 @@ try {
$response["result"] = $mx_db->searchUserByEmail($input["search_term"]);
break;
default:
throw new Exception('unknown type for "by" param');
throw new Exception("unknown type for \"by\" param");
}
} catch (Exception $e) {
error_log("failed with error: " . $e->getMessage());
$response["error"] = $e->getMessage();
}
print (json_encode($response, JSON_PRETTY_PRINT));
print (json_encode($response, JSON_PRETTY_PRINT) . "\n");
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$response = [
"lookup" => []
];
@@ -38,7 +37,7 @@ try {
if (!isset($lookup["address"])) {
throw new Exception('"lookup.address" is not defined');
}
$res2 = NULL;
$res2 = array();
switch ($lookup["medium"]) {
case "email":
$res2 = $mx_db->searchUserByEmail($lookup["address"]);
@@ -55,16 +54,14 @@ try {
}
break;
case "msisdn":
// This is reserved for number lookups
throw new Exception("unimplemented lookup medium");
break;
default:
throw new Exception("unknown lookup medium");
throw new Exception("unknown type for \"by\" param");
}
}
} catch (Exception $e) {
error_log("ídentity_bulk failed with error: " . $e->getMessage());
$response["error"] = $e->getMessage();
}
print (json_encode($response, JSON_PRETTY_PRINT));
print (json_encode($response, JSON_PRETTY_PRINT) . "\n");
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$response = new stdClass;
try {
$inputJSON = file_get_contents('php://input');
@@ -31,7 +30,7 @@ try {
if (!isset($input["lookup"]["address"])) {
throw new Exception('"lookup.address" is not defined');
}
$res2 = NULL;
$res2 = array();
switch ($input["lookup"]["medium"]) {
case "email":
$res2 = $mx_db->searchUserByEmail($input["lookup"]["address"]);
@@ -47,19 +46,15 @@ try {
]
];
}
break;
case "msisdn":
// This is reserved for number lookups
throw new Exception("unimplemented lookup medium");
break;
default:
throw new Exception("unknown lookup medium");
throw new Exception("unknown type for \"by\" param");
}
} catch (Exception $e) {
error_log("ídentity_single failed with error: " . $e->getMessage());
$response = [
"error" => $e->getMessage()
];
error_log("ídentity_bulk failed with error: " . $e->getMessage());
$response["error"] = $e->getMessage();
}
print (json_encode($response, JSON_PRETTY_PRINT));
print (json_encode($response, JSON_PRETTY_PRINT) . "\n");
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// URL for this: /_matrix/client/r0/account/password?access_token=$ACCESS_TOKEN
header('Access-Control-Allow-Origin: *');
@@ -24,7 +24,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
// return with success
exit();
}
$response = new stdClass;
$response= new stdClass;
try {
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);
@@ -44,19 +44,22 @@ try {
throw new Exception('"new_password" is not defined');
}
require_once(__DIR__ . "/../helpers.php");
require_once("../helpers.php");
$localpart = stripLocalpart($input["auth"]["user"]);
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(
$localpart, $input["auth"]["password"], $input["new_password"]
$localpart,
$input["auth"]["password"],
$input["new_password"]
)) {
throw new Exception("invalid credentials or another error while updating");
}
} catch (Exception $e) {
header("HTTP/1.0 500 Internal Error");
error_log("failed with error: " . $e->getMessage());

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,22 +19,19 @@ $response = [
]
];
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
abstract class LoginRequester {
const UNDEFINED = 0;
const MXISD = 1;
const RestAuth = 2;
}
$loginRequester = LoginRequester::UNDEFINED;
try {
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);
$mxid = $localpart = NULL;
$mxid = NULL;
$localpart = NULL;
if (isset($input["user"])) {
if (isset($input["user"]["localpart"])) {
$localpart = $input["user"]["localpart"];
@@ -49,27 +45,25 @@ try {
$mxid = $input["user"]["mxid"];
$loginRequester = LoginRequester::MXISD;
}
} else {
throw new Exception('"user" not in request body');
}
// prefer the localpart attribute of mxisd. But in case of matrix-synapse-rest-auth
// we have to parse it on our own
if (empty($localpart)) {
require_once(__DIR__ . "/../helpers.php");
require_once("../helpers.php");
$localpart = stripLocalpart($mxid);
}
if (empty($localpart)) {
throw new Exception("localpart cannot be identified");
throw new Exception ("localpart cannot be identified");
}
$password = NULL;
if (isset($input["user"]["password"])) {
if (isset($input["user"]) && isset($input["user"]["password"])) {
$password = $input["user"]["password"];
}
if (empty($password)) {
throw new Exception("password is not present");
throw new Exception ("password is not present");
}
$user = $mx_db->getUserForLogin($localpart, $password);
@@ -101,12 +95,11 @@ try {
// only return that it was successful.
// we do not know how the data shall be transmitted so we do nothing with it
$response["auth"]["success"] = false;
$response["auth"]["error"] = "unidentified requester";
break;
}
} catch (Exception $e) {
error_log("Auth failed with error: " . $e->getMessage());
$response["auth"]["error"] = $e->getMessage();
}
print (json_encode($response, JSON_PRETTY_PRINT));
print (json_encode($response, JSON_PRETTY_PRINT) . "\n");
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,57 +14,28 @@
* limitations under the License.
*/
$language = array(
"ACCEPT" => "Akzeptieren",
"DECLINE" => "Ablehnen",
"SUCCESS" => "Erfolgreich",
"FIRST_NAME" => "Vorname",
"LAST_NAME" => "Nachname",
"USERNAME" => "Nutzername (für den Login)",
"PASSWORD" => "Passwort",
"PASSWORD_CONFIRM" => "Passwort bestätigen",
"EMAIL_ADDRESS" => "E-Mail-Adresse",
"REGISTER" => "Registrieren",
"NOTE" => "Hinweis",
"NO_CONFIGURATION" => "Es konnte keine Konfiguration gefunden werden.",
"UNKNOWN_ERROR" => "Unbekannter Fehler",
"UNKNOWN_SESSION" => "Sitzungstoken nicht vorhanden oder ungültig.",
"UNKNOWN_USERNAME" => "Nutzername fehlt",
"UNKNOWN_TOKEN" => "Token ist unbekannt",
"AUTHENTICATION_FAILED" => "Authentifizierung fehlgeschlagen",
"WRONG_REGISTRATION_SHARED_SECRET" => "registration_shared_secret fehlerhaft",
"USERNAME_INVALID" => "Nutzername muss aus 3 bis 20 Kleinbuchstaben bestehen",
"USERNAME_LENGTH_INVALID" => "Entweder mehr als 20 oder weniger als 3 Zeichen für den Nutzernamen verwendet",
"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_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",
"NOTE_LENGTH_EXEEDED" => "Notiz ist länger als die erlaubten 50 Zeichen",
"PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Notiz zu dir (max. 50 Zeichen)",
"EMAIL_INVALID_FORMAT" => "Keine valide E-Mail-Adresse angegeben",
"FIRSTNAME_INVALID_FORMAT" => "Vorname muss das Format <Großbuchstabe><Kleinbuchstaben> haben",
"SIRNAME_INVALID_FORMAT" => "Nachname muss das Format <Großbuchstabe><Kleinbuchstaben> haben",
"FIRSTNAME_INVALID_FORMAT" => "Vorname hat ungültiges Format",
"SIRNAME_INVALID_FORMAT" => "Nachname hat ungültiges Format",
"SEND_MAIL_FAIL" => "Senden der E-Mail fehlgeschlagen",
"SEND_MATRIX_FAIL" => "Senden einer Nachricht an die Administratoren fehlgeschlagen",
"TASK_CHECK_YOUR_EMAIL_VERIFY" => "Bitte prüfe deine E-Mails um deine Adresse zu bestätigen",
"REGISTRATION_REQUEST_FAILED" => "Registrierungsanfrage ist fehlgeschlagen",
"REGISTRATION_FAILED" => "Registrierung ist fehlgeschlagen",
"REGISTRATION_FAILED_FOR" => "Registrierung für @user ist fehlgeschlagen",
"VERIFICATION_SUCEEDED" => "Verifizierung erfolgreich",
"VERIFICATION_FAILED" => "Verifizierung fehlgeschlagen",
"VERIFICATION_SUCCESS_BODY" => "Vielen Dank. Die Administratoren wurden informiert",
"ADMIN_VERIFY_SITE_TITLE" => "Registrierungsanfrage bearbeiten",
"ADMIN_REGISTER_ACCEPTED_BODY" => "Die Registrierungsanfrage wurde akzeptiert. Der Nutzer wurde per Mail informiert.",
"ADMIN_REGISTER_DECLINED_BODY" => "Die Registrierungsanfrage wurde angelehnt. Der Nutzer wurde per Mail informiert.",
"JUMP_TO_HOMEPAGE" => "Zur Startseite",
"TOPIC_PLEASE_REGISTER" => "Bitte für @homeserver registrieren",
"TOPIC_PLEASE_REGISTER_NOTE" => "2-Schritt-Registrierung",
"NOTE_FOR_REGISTRATION" => "@homeserver ist ein geschlossenes Chat-Netzwerk in dem jeder Nutzer bestätigt werden muss.<br />
Du bekommst eine E-Mail wenn jemand deine Mitgliedschaft bestätigt hat. An diese wird auch dein initiales Passwort gesendet.
Hinterlasse also bitte einen Hinweis zu dir (den nur die Administratoren sehen werden).<br />
Liebe Grüße vom Team von @homeserver",
"MSG_USER_WANTS_REGISTER" => "@name möchte sich registrieren und hat folgende Notiz hinterlassen:
@note \r\nZum Bearbeiten hier klicken:\r\n @adminUrl",
"MSG_USER_WANTS_REGISTER_FORMATTED" => "@name möchte sich registrieren und hat folgende Notiz hinterlassen:<br />
@note <br />Zum Bearbeiten <a href=\"@adminUrl\">hier</a> klicken",
);
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,57 +14,28 @@
* limitations under the License.
*/
$language = array(
"ACCEPT" => "Accept",
"DECLINE" => "Decline",
"SUCCESS" => "Success",
"FIRST_NAME" => "First name",
"LAST_NAME" => "Last name",
"USERNAME" => "username (for login)",
"PASSWORD" => "Password",
"PASSWORD_CONFIRM" => "Confirm password",
"EMAIL_ADDRESS" => "EMail Address",
"REGISTER" => "Register",
"NOTE" => "Note",
"NO_CONFIGURATION" => "No configuration found",
"UNKNOWN_ERROR" => "Unknown Error",
"UNKNOWN_SESSION" => "Session token not found of invalid.",
"UNKNOWN_USERNAME" => "username unknown",
"UNKNOWN_TOKEN" => "Token is unknown",
"AUTHENTICATION_FAILED" => "Authentication failed",
"WRONG_REGISTRATION_SHARED_SECRET" => "wrong registration_shared_secret",
"USERNAME_INVALID" => "Username has to consist of 3 to 20 small letters",
"USERNAME_LENGTH_INVALID" => "Username cpnsists pf more than 20 or less than 3 characters",
"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_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",
"NOTE_LENGTH_EXEEDED" => "Note consists of more than 50 characters",
"PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Note about yourself (max. 50 characters)",
"EMAIL_INVALID_FORMAT" => "no valid email address",
"FIRSTNAME_INVALID_FORMAT" => "First name with invalid formatting",
"SIRNAME_INVALID_FORMAT" => "Sirname with invalid formatting",
"SEND_MAIL_FAIL" => "Email could not be sent",
"SEND_MATRIX_FAIL" => "Sending a message to the admins failed",
"TASK_CHECK_YOUR_EMAIL_VERIFY" => "Please check your emails to verify your email address",
"REGISTRATION_REQUEST_FAILED" => "Registration request failed",
"REGISTRATION_FAILED" => "Registration failed",
"REGISTRATION_FAILED_FOR" => "Registrierung für @user ist fehlgeschlagen",
"VERIFICATION_SUCEEDED" => "Verification suceeded",
"VERIFICATION_FAILED" => "Verification failed",
"VERIFICATION_SUCCESS_BODY" => "Thank you. The admins got informed",
"ADMIN_VERIFY_SITE_TITLE" => "Handle registration request",
"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.",
"JUMP_TO_HOMEPAGE" => "To homepage",
"TOPIC_PLEASE_REGISTER" => "Please register for @homeserver",
"TOPIC_PLEASE_REGISTER_NOTE" => "2-Step-Registration",
"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.
Please leave a note about yourself (that will only be shown to the admins).<br />
Greetings from the team of @homeserver",
"MSG_USER_WANTS_REGISTER" => "@name wants to register and left the following note:
@note \r\nTo handle that request:\r\n @adminUrl",
"MSG_USER_WANTS_REGISTER_FORMATTED" => "@name wants to register and left the following note:<br />
@note <br />To handle that request click <a href=\"@adminUrl\">here</a>",
);
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,7 @@
* limitations under the License.
*/
function send_mail($receiver, $subject, $body) {
include(__DIR__ . "/../config.php");
include("config.php");
$headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers);
@@ -40,7 +39,7 @@ Danach ist eine Re-Registrierung mit deinem gewünschten Nutzernamen für andere
Vielen Dank für dein Verständnis.
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) {
@@ -54,7 +53,7 @@ Du bekommst eine weitere E-Mail, sobald deine Registrierung bestätigt oder able
Vielen Dank für dein Verständnis.
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) {
@@ -69,6 +68,7 @@ Wir melden uns, wenn die Registrierung erfolgreich war.
Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body);
}
function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) {
@@ -79,30 +79,30 @@ Deine Registrierungsanfrage wurde durch die Administratoren bestätigt.
Zum Anmelden kannst du folgende Zugangsdaten verwenden:
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
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.
Es wird zwar von unserer Seite nicht gespeichert, doch fremde könnten Zugriff auf diese E-Mail
erhalten und so deinen Account kompromittieren.
/*
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
erhalten und so deinen Account kompromittieren.
*/
if (!empty($howToURL)) {
if (!empty($howToURL)) {
$body .= "
Zu weiteren Hilfestellungen findest du hier eine Auflistung von verschiedenen
Anleitungen zu verschiedenen Clients:
$howToURL\n";
}
}
$body .= "
Viel Spaß bei der Verwendung von $homeserver.
Bei Fragen findest du nach der Anmeldung ein paar Räume in denen du sie stellen kannst.
Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body);
}
}
function send_mail_registration_decline($homeserver, $user, $receiver, $reason) {
$subject = "Registrierung auf $homeserver abgelehnt";
$body = "Guten Tag " . $user . ",
@@ -119,7 +119,6 @@ Deine Registrierungsanfrage wurde durch die Administratoren abgelehnt.\n";
Wir hoffen, dass du dies akzeptieren kannst.
Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body);
return send_mail($receiver, $subject, $body );
}
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,7 @@
* limitations under the License.
*/
function send_mail($receiver, $subject, $body) {
include(__DIR__ . "/../config.php");
include("config.php");
$headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers);
@@ -39,7 +38,7 @@ Others might take your username afterwards.
Thanks for your patience.
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) {
@@ -53,7 +52,7 @@ You will get an email once they approve or decline your request.
Sincerely,
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) {
@@ -68,6 +67,7 @@ You will get another email with initial credentials once the registration got ha
The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body);
}
function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) {
@@ -78,25 +78,25 @@ Your registration request got verified by the admin team.
To log in you can use the following credentials::
Username: $username
Passwort: " . (empty($password) ? "as self-set": $password) . "
Password: $password
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
and compromise your account.
";
if (!empty($howToURL)) {
if (!empty($howToURL)) {
$body .= "
You can find further help here::
$howToURL\n";
}
}
$body .= "
Enjoy your usage of $homeserver.
You can ask further questions inside of the chat system.
The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body);
}
}
function send_mail_registration_decline($homeserver, $user, $receiver, $reason) {
$subject = "Registration on $homeserver declined.";
$body = "Guten Tag " . $user . ",
@@ -113,7 +113,6 @@ Your registration request got declined by the admin team.\n";
We hope that you can understand this reason.
The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body);
return send_mail($receiver, $subject, $body );
}
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,18 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
$lang = $config["defaultLanguage"];
require_once("config.php");
$lang=$config["defaultLanguage"];
if (isset($_GET['lang'])) {
if(isset($_GET['lang'])){
$lang = filter_var($_GET['lang'], FILTER_SANITIZE_STRING);
}
$lang_file = dirname(__FILE__) . "/lang/lang." . $lang . ".php";
$lang_file = dirname(__FILE__) . "/lang/lang.".$lang.".php";
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_file = __DIR__ . "/lang/lang." . $lang . ".php";
require_once($lang_file);
unset($lang_file);
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,17 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
$lang = $config["defaultLanguage"];
if (isset($_GET['lang'])) {
require_once("config.php");
$lang=$config["defaultLanguage"];
if(isset($_GET['lang'])){
$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)) {
error_log("Mail templates for '" . $lang . "' not found. Fallback to 'de-de'");
$lang = "de-de";
}
$lang_file = __DIR__ . "/lang/mail." . $lang . ".php";
require_once($lang_file);
unset($lang_file);
?>

View File

@@ -13,31 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// enforce admin via https
if (!isset($_SERVER['HTTPS'])) {
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
exit();
}
require_once(__DIR__ . "/../language.php");
require_once "../language.php";
if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]);
exit();
}
require_once(__DIR__ . "/../config.php");
require_once "../config.php";
// this values will not be used when using the register operation type
$storeFirstLastName = false;
if (isset($config["operationMode"]) && $config["operationMode"] === "local") {
$storeFirstLastName = true;
// enforce admin via https
if (!isset($_SERVER['HTTPS'])) {
header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
exit();
}
// currently the case to store the password on our own is the only supported one
$storePassword = false;
if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"] &&
isset($config["operationMode"]) && $config["operationMode"] === "synapse") {
$storePassword = true;
}
session_start();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
@@ -49,18 +37,14 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!isset($_POST["username"])) {
throw new Exception("UNKNOWN_USERNAME");
}
if (strlen($_POST["username"]) > 20 ||
strlen($_POST["username"]) < 3 ||
!ctype_lower($_POST["username"])) {
throw new Exception("USERNAME_INVALID");
if (strlen($_POST["username"] > 20 || strlen($_POST["username"]) < 3)) {
throw new Exception("USERNAME_LENGTH_INVALID");
}
if (ctype_alnum($_POST['username']) != true) {
throw new Exception("USERNAME_NOT_ALNUM");
}
if ($storePassword && (!isset($_POST["password"]) || !isset($_POST["password_confirm"]))) {
throw new Exception("PASSWORD_NOT_PROVIDED");
}
if ($storePassword && $_POST["password"] != $_POST["password_confirm"]) {
if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"] &&
$_POST["password"] != $_POST["password_confirm"]) {
throw new Exception("PASSWORD_NOT_MATCH");
}
if (isset($_POST["note"]) && strlen($_POST["note"]) > 50) {
@@ -69,50 +53,48 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!isset($_POST["email"]) || !filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
throw new Exception("EMAIL_INVALID_FORMAT");
}
if ($storeFirstLastName) {
// only require first_name and last_name when we will evaluate them
if (!isset($_POST["first_name"]) || !preg_match("/[A-Z][a-z]+/", $_POST["first_name"])) {
if (isset($_POST["first_name"]) && ! preg_match("/[A-Z][a-z]+/", $_POST["first_name"])) {
throw new Exception("FIRSTNAME_INVALID_FORMAT");
}
if (!isset($_POST["last_name"]) || !preg_match("/[A-Z][a-z]+/", $_POST["last_name"])) {
if (isset($_POST["last_name"]) && ! preg_match("/[A-Z][a-z]+/", $_POST["last_name"])) {
throw new Exception("SIRNAME_INVALID_FORMAT");
}
$first_name = filter_var($_POST["first_name"], FILTER_SANITIZE_STRING);
$last_name = filter_var($_POST["last_name"], FILTER_SANITIZE_STRING);
} else {
$first_name = $last_name = "";
}
$username = filter_var($_POST["username"], FILTER_SANITIZE_STRING);
$password = "";
if ($storePassword && isset($_POST["password"])) {
if (isset($_POST["password"])) {
$password = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
}
$note = filter_var($_POST["note"], FILTER_SANITIZE_STRING);
$email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
require_once(__DIR__ . "/../database.php");
$res = $mx_db->addRegistration($first_name, $last_name, $username, $password, $note, $email);
require_once("../database.php");
$res = $mx_db->addRegistration($first_name, $last_name, $username, $note, $email);
if (!isset($res["verify_token"])) {
error_log("sth. went wrong. registration did not throw but admin_token not set");
throw Exception("UNKNOWN_ERROR");
throw Exception ("Unknown Error");
}
$verify_token = $res["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(
$config["homeserver"], $storeFirstLastName ? $first_name . " " . $last_name : $username, $email, $verify_url);
$config["homeserver"],
$first_name . " " . $last_name,
$email,
$verify_url);
$mx_db->setRegistrationStateVerify(
($success ? RegisterState::PendingEmailVerify : RegisterState::PendingEmailSend), $verify_token);
($success ? RegisterState::PendingEmailVerify : RegisterState::PendingEmailSend),
$verify_token);
print("<title>" . $language["SUCCESS"] . "</title>");
print("<title>Erfolgreich</title>");
print("</head><body>");
print("<h1>" . $language["SUCCESS"] . "</h1>");
print("<p>" . $language["TASK_CHECK_YOUR_EMAIL_VERIFY"] . "</p>");
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>");
print("<h1>Erfolgreich</h1>");
print("<p>Bitte überprüfe deine E-Mails um deine E-Mail-Adresse zu bestätigen.</p>");
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
} catch (Exception $e) {
print("<title>" . $language["REGISTRATION_REQUEST_FAILED"] . "</title>");
print("</head><body>");
@@ -122,130 +104,123 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
} else {
print("<p>" . $e->getMessage() . "</p>");
}
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>");
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
}
} else {
$_SESSION["token"] = bin2hex(random_bytes(16));
?>
<title><?php echo strtr($language["TOPIC_PLEASE_REGISTER"], ["@homeserver" => $config["homeserver"]]); ?></title>
?>
<title>Registriere dich für <?php echo $config["homeserver"]; ?></title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet">
<style>
body{
body{
background-color: #525252;
}
.centered-form{
}
.centered-form{
margin-top: 60px;
}
}
.centered-form .panel{
.centered-form .panel{
background: rgba(255, 255, 255, 0.8);
box-shadow: rgba(0, 0, 0, 0.3) 20px 20px 20px;
}
}
</style>
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
</head>
<body>
</head>
<body>
<div class="container">
<div class="row centered-form">
<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-heading">
<h3 class="panel-title"><?php
echo strtr($language["TOPIC_PLEASE_REGISTER"], ["@homeserver" => $config["homeserver"]])
. "<small>" . $language["TOPIC_PLEASE_REGISTER_NOTE"] . "</small>";
?></h3>
<h3 class="panel-title">Bitte für <?php echo $config["homeserver"]; ?> registrieren<small>2-Schritt-Registrierung</small></h3>
</div>
<div class="panel-body">
<form name="regForm" role="form" action="index.php" method="post">
<?php if ($storeFirstLastName) { ?>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="text" name="first_name" id="first_name" class="form-control input-sm"
placeholder="<?php echo $language["FIRST_NAME"]; ?>" pattern="[A-Z][a-z]+">
placeholder="Vorname" pattern="[A-Z][a-z]+">
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="text" name="last_name" id="last_name" class="form-control input-sm"
placeholder="<?php echo $language["LAST_NAME"]; ?>" pattern="[A-Z][a-z]+">
placeholder="Nachname" pattern="[A-Z][a-z]+">
</div>
</div>
</div>
<?php } ?>
<div class="form-group">
<input type="email" name="email" id="email" class="form-control input-sm" placeholder="<?php echo $language["EMAIL_ADDRESS"]; ?>" required>
</div>
<div class="form-group">
<input type="text" name="note" id="note" class="form-control input-sm" placeholder="<?php echo $language["PLACEHOLDER_NOTE_ABOUT_YOURSELF"]; ?>">
<input type="email" name="email" id="email" class="form-control input-sm" placeholder="E-Mail-Adresse" required>
</div>
<div class="form-group">
<input type="text" name="note" id="note" class="form-control input-sm" placeholder="Notiz zu dir (max. 50 Zeichen)">
</div>
<div class="form-group">
<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="Nutzername (für den Login)" pattern="[a-z1-9]{3,20}" required>
</div>
<?php if ($storePassword) { ?>
<?php if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"]) { ?>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-sm" placeholder="<?php echo $language["PASSWORD"]; ?>" required>
<input type="password" name="password" id="password" class="form-control input-sm" placeholder="Passwort" required>
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="password" name="password_confirm" id="password_confirm" class="form-control input-sm" placeholder="<?php echo $language["PASSWORD_CONFIRM"]; ?>" required>
<input type="password" name="password_confirm" id="password_confirm" class="form-control input-sm" placeholder="Passwort bestätigen" required>
</div>
</div>
</div>
<?php } ?>
<?php } ?>
<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="Registrieren" class="btn btn-info btn-block">
</form>
<?php
if (isset($language["NOTE_FOR_REGISTRATION"])) {
echo "<p>" . $language["NOTE"] . ": <br />";
echo strtr($language["NOTE_FOR_REGISTRATION"], ["@homeserver" => $config["homeserver"]]);
echo "</p>";
}
?>
<p>Hinweis: <br />
<?php echo $config["homeserver"]; ?> ist ein geschlossenes Chat-Netzwerk in dem jeder Nutzer bestätigt werden muss.<br />
Du bekommst eine E-Mail wenn jemand deine Mitgliedschaft bestätigt hat. An diese wird auch dein initiales Passwort gesendet.
Hinterlasse also bitte einen Hinweis zu dir (der nur den entsprechenden Personen gezeigt wird).<br />
Liebe Grüße vom Team von <?php echo $config["homeserver"]; ?>
</p>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var first_name = document.getElementById("first_name");
first_name.oninvalid = function(event) {
event.target.setCustomValidity("Vorname muss das Format <Großbuchstabe><Kleinbuchstaben> haben");
}
first_name.onkeyup = function(event) {
event.target.setCustomValidity("");
}
var last_name = document.getElementById("last_name");
last_name.oninvalid = function(event) {
event.target.setCustomValidity("Nachname muss das Format <Großbuchstabe><Kleinbuchstaben> haben");
}
last_name.onkeyup = function(event) {
event.target.setCustomValidity("");
}
var user_name = document.getElementById("username");
user_name.oninvalid = function (event) {
event.target.setCustomValidity("<?php echo $language["USERNAME_INVALID"]; ?>");
user_name.oninvalid = function(event) {
event.target.setCustomValidity("Nutzername darf zwischen 3 und 20 kleine Buchstaben und Zahlen enthalten");
}
user_name.onkeyup = function (event) {
event.target.setCustomValidity("");
}
<?php if ($storeFirstLastName) { ?>
var first_name = document.getElementById("first_name");
first_name.oninvalid = function (event) {
event.target.setCustomValidity("<?php echo $language["FIRSTNAME_INVALID_FORMAT"]; ?>");
}
first_name.onkeyup = function (event) {
event.target.setCustomValidity("");
}
var last_name = document.getElementById("last_name");
last_name.oninvalid = function (event) {
event.target.setCustomValidity("<?php echo $language["SIRNAME_INVALID_FORMAT"]; ?>");
}
last_name.onkeyup = function (event) {
event.target.setCustomValidity("");
}
<?php } if ($storePassword) { ?>
<?php if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"]) { ?>
var password = document.getElementById("password")
, confirm_password = document.getElementById("password_confirm");
function validatePassword() {
if (password.value != confirm_password.value) {
confirm_password.setCustomValidity("<?php echo $language["PASSWORD_NOT_MATCH"]; ?>");
function validatePassword(){
if(password.value != confirm_password.value) {
confirm_password.setCustomValidity("Passwörter stimmen nicht überein");
} else {
confirm_password.setCustomValidity('');
}
@@ -253,6 +228,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
password.onchange = validatePassword;
confirm_password.onkeyup = validatePassword;
<?php } ?>
</script>
<?php } ?>
</body></html>
</script>
<?php } ?>
</body>
</html>

View File

@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../language.php");
require_once "../language.php";
if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]);
exit();
}
require_once(__DIR__ . "/../config.php");
require_once(__DIR__ . "/../mail_templates.php");
require_once "../config.php";
require_once "../mail_templates.php";
// enforce admin via https
if (!isset($_SERVER['HTTPS'])) {
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
exit();
}
@@ -38,7 +38,7 @@ try {
}
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$user = $mx_db->getUserForVerify($token);
if ($user == NULL) {
@@ -46,27 +46,20 @@ try {
}
$first_name = $user["first_name"];
$last_name = $user["last_name"];
$username = $user["username"];
$note = $user["note"];
$email = $user["email"];
$admin_token = $user["admin_token"];
require_once(__DIR__ . "/../MatrixConnection.php");
require_once("../MatrixConnection.php");
$adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $admin_token;
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$mxMsg = new MatrixMessage();
$mxMsg->set_body(strtr($language["MSG_USER_WANTS_REGISTER"], [
"@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note,
"@adminUrl" => $adminUrl
]));
if (isset($language["MSG_USER_WANTS_REGISTER_FORMATTED"])) {
$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_body($first_name . ' ' . $last_name . "möchte sich registrieren und hat folgende Notiz hinterlassen:\r\n"
. $note . "\r\n"
. "Zum Bearbeiten hier klicken:\r\n" . $adminUrl);
$mxMsg->set_formatted_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:<br />"
. $note . "<br />"
. "Zum Bearbeiten <a href=\"". $adminUrl . "\">hier</a> klicken");
$mxMsg->set_type("m.text");
$response = $mxConn->send($config["register_room"], $mxMsg);
@@ -74,7 +67,8 @@ try {
$message = $language["SEND_MATRIX_FAIL"];
}
$mx_db->setRegistrationStateVerify(
($response ? RegisterState::PendingAdminVerify : RegisterState::PendingAdminSend), $token);
($response ? RegisterState::PendingAdminVerify : RegisterState::PendingAdminSend),
$token);
send_mail_pending_approval($config["homeserver"], $first_name . " " . $last_name, $email);
@@ -82,7 +76,7 @@ try {
print("</head><body>");
print("<h1>" . $language["VERIFICATION_SUCEEDED"] . "</h1>");
print("<p>" . $language["VERIFICATION_SUCCESS_BODY"] . "</p>");
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>");
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
} catch (Exception $e) {
print("<title>" . $language["VERIFICATION_FAILED"] . "</title>");
print("</head><body>");
@@ -92,7 +86,7 @@ try {
} else {
print("<p>" . $e->getMessage() . "</p>");
}
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>");
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
}
?>
</body>

View File

@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../language.php");
require_once "../language.php";
if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]);
exit();
}
require_once(__DIR__ . "/../config.php");
require_once(__DIR__ . "/../mail_templates.php");
require_once "../config.php";
require_once "../mail_templates.php";
// enforce admin via https
if (!isset($_SERVER['HTTPS'])) {
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], true, 301);
header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
exit();
}
@@ -38,7 +38,7 @@ try {
}
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$action = NULL;
if (isset($_GET["allow"])) {
@@ -67,45 +67,14 @@ try {
$mx_db->setRegistrationStateAdmin(RegisterState::PendingRegistration, $token);
// register user
require_once(__DIR__ . "/../MatrixConnection.php");
require_once("../MatrixConnection.php");
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$password = NULL;
$use_db_password = (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"]);
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");
}
// generate a password with 8 characters
$password = $mx_db->addUser($first_name, $last_name, $username, $email);
if ($password != NULL) {
// send registration_success
$res = send_mail_registration_success(
$config["homeserver"],
$first_name . " " . $last_name,
$email,
$username,
// only send password when auto-created
($use_db_password ? NULL : $password),
$config["howToURL"]
);
$res = send_mail_registration_success($config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]);
if ($res) {
$mx_db->setRegistrationStateAdmin(RegisterState::AllDone, $token);
} else {
@@ -115,9 +84,7 @@ try {
send_mail_registration_allowed_but_failed($config["homeserver"], $first_name . " " . $last_name, $email);
$mxMsg = new MatrixMessage();
$mxMsg->set_type("m.text");
$mxMsg->set_body(strtr($language["REGISTRATION_FAILED_FOR"], [
"@name" => strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username,
]));
$mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . ".");
$mxConn->send($config["register_room"], $mxMsg);
throw new Exception("REGISTRATION_FAILED");
}
@@ -128,9 +95,7 @@ try {
print("<p>" . $language["ADMIN_REGISTER_ACCEPTED_BODY"] . "</p>");
} elseif ($action == RegisterState::RegistrationDeclined) {
$mx_db->setRegistrationStateAdmin(RegisterState::RegistrationDeclined, $token);
send_mail_registration_decline(
$config["homeserver"], strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username, $email, $decline_reason
);
send_mail_registration_decline($config["homeserver"], $first_name . " " . $last_name, $email, $decline_reason);
print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>");
print("</head><body>");
print("<h1>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</h1>");
@@ -149,7 +114,7 @@ try {
}
.centered-form .panel{
background: rgba(255, 255, 255, 0.8);
background: rgba(255, 255, 255, 0.8);
box-shadow: rgba(0, 0, 0, 0.3) 20px 20px 20px;
}
</style>
@@ -162,14 +127,10 @@ try {
<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-heading">
<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 class="panel-body">
<form name="appForm" role="form" action="verify_admin.php" method="GET">
<?php
if (isset($config["operationMode"]) && $config["operationMode"] === "local") {
// this values will not be used when using the register operation type
?>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
@@ -184,7 +145,7 @@ try {
</div>
</div>
</div>
<?php } ?>
<div class="form-group">
<input type="text" id="note" class="form-control input-sm" value="<?php echo $note; ?>" disabled=true>
</div>
@@ -194,8 +155,9 @@ try {
value="<?php echo $username; ?>" disabled=true>
</div>
<input type="hidden" name="t" id="token" value="<?php echo $token; ?>">
<input type="submit" name="allow" value="<?php echo $language["ACCEPT"]; ?>" class="btn btn-info btn-block">
<input type="submit" name="deny" value="<?php echo $language["DECLINE"]; ?>" class="btn btn-info btn-block">
<input type="submit" name="allow" value="Bestätigen" class="btn btn-info btn-block">
<input type="submit" name="deny" value="Ablehnen" class="btn btn-info btn-block">
</form>
</div>
</div>
@@ -206,7 +168,7 @@ try {
<?php
} // else - no action provided
} catch (Exception $e) {
} catch (Exception $e) {
print("<title>" . $language["REGISTRATION_FAILED"] . "</title>");
print("</head><body>");
print("<h1>" . $language["REGISTRATION_FAILED"] . "</h1>");
@@ -215,8 +177,8 @@ try {
} else {
print("<p>" . $e->getMessage() . "</p>");
}
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">" . $language["JUMP_TO_HOMEPAGE"] . "</a>");
}
?>
</body>
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
}
?>
</body>
</html>