12 Commits

Author SHA1 Message Date
ffce2fc28b run some autoformat 2018-04-04 20:43:24 +02:00
eb5b76c5c8 smaller optimizations 2018-04-04 20:29:00 +02:00
Matthias
b343c6f862 Update readme to have howTo for ChangePasswordInterceptor 2018-03-26 23:27:04 +02:00
6f6ad7bccb fix password setting via android; update mail_template to show that you can set passwords 2018-03-26 19:26:14 +02:00
4f76e45ae5 fix login 2018-03-26 18:08:17 +02:00
874271a87c first version of change_password interceptor (more see details)
- add stripLocalpart in helpers.php
- extend mxDatabase to update the password once validated
2018-03-26 13:28:04 +02:00
905643cbff Merge branch 'master' 2018-03-19 15:18:29 +01:00
f986867cad apply Apache License 2018-03-19 15:18:04 +01:00
Matthias
916e368b00 fix rendering of table of endpoints for internal endpoints 2018-03-19 15:04:26 +01:00
Matthias
6df1eaa7a1 Merge branch 'fix_language_ref' of into master 2018-03-19 14:48:48 +01:00
facdad126b fix language reference
it was the case that the language string for Exceptions was not
resolved successfully in some cases.
Now we switch to passing the internal string via Exceptions which
then will be used to translate to the correct language when needed
2018-03-19 14:40:20 +01:00
Matthias
d5c18c2f2e First running version (#2)
This currently depends of interacting with matrix_synapse_rest_auth[1] and mxisd[2].
How to integrate that is explained in the README

[1] https://github.com/kamax-io/matrix-synapse-rest-auth
[2] https://github.com/kamax-io/mxisd
2018-03-19 13:57:15 +01:00
17 changed files with 940 additions and 613 deletions

View File

@@ -1,155 +1,170 @@
<?php <?php
class MatrixConnection
{
private $hs;
private $at;
function __construct($homeserver, $access_token) { /**
$this->hs = $homeserver; * Copyright 2018 Matthias Kesler
$this->at = $access_token; * 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.
*/
class MatrixConnection {
function send($room_id, $message) { private $hs;
if (!$this->at) { private $at;
error_log("No access token defined");
return false;
}
$send_message = NULL; function __construct($homeserver, $access_token) {
if (!$message) { $this->hs = $homeserver;
error_log("no message to send"); $this->at = $access_token;
return false; }
} elseif(is_array($message)) {
$send_message = $message;
} elseif ($message instanceof MatrixMessage) {
$send_message = $message->get_object();
} else {
error_log("message is of not valid type\n");
return false;
}
$url="https://".$this->hs."/_matrix/client/r0/rooms/" function send($room_id, $message) {
. urlencode($room_id) ."/send/m.room.message?access_token=".$this->at; if (!$this->at) {
$handle = curl_init($url); error_log("No access token defined");
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); return false;
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_HTTPHEADER, array("Content-Type: application/json"));
$response = $this->exec_curl_request($handle); $send_message = NULL;
return isset($response["event_id"]); if (!$message) {
} error_log("no message to send");
return false;
} elseif (is_array($message)) {
$send_message = $message;
} elseif ($message instanceof MatrixMessage) {
$send_message = $message->get_object();
} else {
error_log("message is of not valid type\n");
return false;
}
function send_msg($room_id, $message) { $url = "https://" . $this->hs . "/_matrix/client/r0/rooms/"
return $this->send($room_id, array( . urlencode($room_id) . "/send/m.room.message?access_token=" . $this->at;
"msgtype" => "m.notice", $handle = curl_init($url);
"body" => $message 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_HTTPHEADER, array("Content-Type: application/json"));
function hasUser($username) { $response = $this->exec_curl_request($handle);
if (!$username) { return isset($response["event_id"]);
throw new Exception ("no user given to lookup"); }
}
$url = "https://".$this->hs."/_matrix/client/r0/profile/@" . $username . ":" . $this->hs; function send_msg($room_id, $message) {
$handle = curl_init($url); return $this->send($room_id, array(
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); "msgtype" => "m.notice",
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5); "body" => $message
curl_setopt($handle, CURLOPT_TIMEOUT, 60); )
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json")); );
}
$res = $this->exec_curl_request($handle); function hasUser($username) {
return !(isset($res["errcode"]) && $res["errcode"] == "M_UNKNOWN"); if (!$username) {
} throw new Exception("no user given to lookup");
}
function register($username, $password, $shared_secret) { $url = "https://" . $this->hs . "/_matrix/client/r0/profile/@" . $username . ":" . $this->hs;
if (!$username) { $handle = curl_init($url);
error_log("no username provided"); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
} curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
if (!$password) { curl_setopt($handle, CURLOPT_TIMEOUT, 60);
error_log("no message to send"); curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
}
$mac = hash_hmac('sha1', $username, $shared_secret); $res = $this->exec_curl_request($handle);
return !(isset($res["errcode"]) && $res["errcode"] == "M_UNKNOWN");
}
$data = array( function register($username, $password, $shared_secret) {
"username" => $username, if (!$username) {
"password" => $password, error_log("no username provided");
"mac" => $mac, }
); if (!$password) {
$url = "https://".$this->hs."/_matrix/client/v2_alpha/register"; error_log("no message to send");
$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));
return $this->exec_curl_request($handle); $mac = hash_hmac('sha1', $username, $shared_secret);
}
function exec_curl_request($handle) { $data = array(
$response = curl_exec($handle); "username" => $username,
"password" => $password,
"mac" => $mac,
);
$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);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($data));
if ($response === false) { return $this->exec_curl_request($handle);
$errno = curl_errno($handle); }
$error = curl_error($handle);
error_log("Curl returned error $errno: $error\n");
curl_close($handle);
return false;
}
$http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE)); function exec_curl_request($handle) {
curl_close($handle); $response = curl_exec($handle);
if ($response === false) {
$errno = curl_errno($handle);
$error = curl_error($handle);
error_log("Curl returned error $errno: $error\n");
curl_close($handle);
return false;
}
$http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE));
curl_close($handle);
if ($http_code >= 500) { if ($http_code >= 500) {
// do not want to DDOS server if something goes wrong // do not want to DDOS server if something goes wrong
sleep(10); sleep(10);
return false; return false;
} else if ($http_code != 200) { } else if ($http_code != 200) {
$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('Invalid access token provided'); throw new Exception('Invalid access token provided');
} }
} else { } else {
$response = json_decode($response, true); $response = json_decode($response, true);
} }
return $response;
}
return $response;
}
} }
class MatrixMessage class MatrixMessage {
{
private $message;
function __construct() { private $message;
$this->message = ["msgtype" => "m.notice"];
}
function set_type($msgtype) { function __construct() {
$this->message["msgtype"] = $msgtype; $this->message = ["msgtype" => "m.notice"];
} }
function set_format($format) { function set_type($msgtype) {
$this->message["format"] = $format; $this->message["msgtype"] = $msgtype;
} }
function set_body($body) { function set_format($format) {
$this->message["body"] = $body; $this->message["format"] = $format;
} }
function set_formatted_body($fbody, $format="org.matrix.custom.html") { function set_body($body) {
$this->message["formatted_body"] = $fbody; $this->message["body"] = $body;
$this->message["format"] = $format; }
}
function set_formatted_body($fbody, $format = "org.matrix.custom.html") {
$this->message["formatted_body"] = $fbody;
$this->message["format"] = $format;
}
function get_object() {
return $this->message;
}
function get_object() {
return $this->message;
}
} }
?> ?>

View File

@@ -14,17 +14,34 @@ This is done in several steps:
2nd step: Implement the other apis to integrade [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md) 2nd step: Implement the other apis to integrade [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md)
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 - Copy `config.sample.php` to `config.php` and configure the bot as you can find there
- Configure your webserver to publish the folder `public` and configure. - Configure your webserver to publish the folder `public`.
The folder `internal` contains files that can be accessed by mxisd or matrix-synapse-rest-auth The folder `internal` contains files that can be accessed by mxisd or matrix-synapse-rest-auth or else via a reverse proxy
- To integrate with 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: Have a look at [the docs](https://github.com/kamax-io/mxisd/blob/master/docs/backends/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 |
|--------------------------------|-------------------------------|------------------------------------------------------| |--------------------------------|-------------------------------|------------------------------------------------------|
| rest.endpoints.auth | internal/login.php | Validate credentials and get user profile | | rest.endpoints.auth | internal/login.php | Validate credentials and get user profile |
| rest.endpoints.directory | internal/directory_search.php | Search for users by arbitrary input | | 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.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 | | rest.endpoints.identity.bulk | internal/identity_bulk.php | Endpoint to query a list of 3PID |
## Implement usage of additional features:
### Use the ChangePasswortInterceptor:
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;
}
```

View File

@@ -1,26 +1,22 @@
<?php <?php
$config = [ $config = [
"homeserver" => "example.com", "homeserver" => "example.com",
"access_token" => "To be used for sending the registration notification", "access_token" => "To be used for sending the registration notification",
// 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', // 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', // Where is the public part of the bot located? make sure you have a / at the end
"webroot" => "https://myregisterdomain.net/",
// Where is the public part of the bot located? make sure you have a / at the end // optional: Do you have a place where howTo's are located? If not leave this value out
"webroot" => "https://myregisterdomain.net/", "howToURL" => "https://my-url-for-storing-howTos.net",
// When you want to collect the password on registration set this to true
// optional: Do you have a place where howTo's are located? If not leave this value out "getPasswordOnRegistration" => false,
"howToURL" => "https://my-url-for-storing-howTos.net", // to define where the data should be stored:
"databaseURI" => "sqlite:" . dirname(__FILE__) . "/db_file.sqlite",
// When you want to collect the password on registration set this to true // credentials for sqlite not used
"getPasswordOnRegistration" => false, "databaseUser" => "dbUser123",
"databasePass" => "secretPassword",
// to define where the data should be stored: ]
"databaseURI" => "sqlite:" . dirname(__FILE__) . "/db_file.sqlite",
// credentials for sqlite not used
"databaseUser" => "dbUser123",
"databasePass" => "secretPassword",
]
?> ?>

168
cron.php
View File

@@ -1,92 +1,104 @@
<?php <?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.
*/
require_once("config.php"); require_once("config.php");
require_once("mail_templates.php"); require_once("mail_templates.php");
require_once("database.php"); require_once("database.php");
$sql = "SELECT id, first_name, last_name, username, email, state, note, verify_token, admin_token FROM registrations " $sql = "SELECT id, first_name, last_name, username, email, 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::RegistrationDeclined
. " OR state = " . RegisterState::AllDone . ";"; . " 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"];
$username = $row["username"]; $username = $row["username"];
$email = $row["email"]; $email = $row["email"];
$state = $row["state"]; $state = $row["state"];
try { try {
switch ($state) { switch ($state) {
case RegisterState::PendingEmailSend: case RegisterState::PendingEmailSend:
$verify_url = $config["webroot"] . "/verify.php?t=" . $row["verify_token"]; $verify_url = $config["webroot"] . "/verify.php?t=" . $row["verify_token"];
$success = send_mail_pending_verification( $success = send_mail_pending_verification(
$config["homeserver"], $config["homeserver"], $row["first_name"] . " " . $row["last_name"], $row["email"], $verify_url);
$row["first_name"] . " " . $row["last_name"],
$row["email"],
$verify_url);
if ($success) { if ($success) {
$mx_db->setRegistrationStateById(RegisterState::PendingEmailVerify, $row["id"]); $mx_db->setRegistrationStateById(RegisterState::PendingEmailVerify, $row["id"]);
} else { } 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; break;
case RegisterState::PendingAdminSend: case RegisterState::PendingAdminSend:
require_once("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($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:\r\n" $mxMsg->set_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:\r\n"
. $row["note"] . "\r\n" . $row["note"] . "\r\n"
. "Zum Bearbeiten hier klicken:\r\n" . $adminUrl); . "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 />" $mxMsg->set_formatted_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:<br />"
. $row["note"] . "<br />" . $row["note"] . "<br />"
. "Zum Bearbeiten <a href=\"". $adminUrl . "\">hier</a> klicken"); . "Zum Bearbeiten <a href=\"" . $adminUrl . "\">hier</a> klicken");
$mxMsg->set_type("m.text"); $mxMsg->set_type("m.text");
$response = $mxConn->send($config["register_room"], $mxMsg); $response = $mxConn->send($config["register_room"], $mxMsg);
if ($response) { if ($response) {
$mx_db->setRegistrationStateById(RegisterState::PendingAdminVerify, $row["id"]); $mx_db->setRegistrationStateById(RegisterState::PendingAdminVerify, $row["id"]);
send_mail_pending_approval($config["homeserver"], $first_name . " " . $last_name, $email); send_mail_pending_approval($config["homeserver"], $first_name . " " . $last_name, $email);
} else { } 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; break;
case RegisterState::PendingRegistration: case RegisterState::PendingRegistration:
// Registration got accepted but registration failed // Registration got accepted but registration failed
$password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["email"]); $password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["email"]);
if ($password != NULL) { if ($password != NULL) {
// send registration_success // send registration_success
$res = send_mail_registration_success($config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]); $res = send_mail_registration_success($config["homeserver"], $first_name . " " . $last_name, $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 {
$mx_db->setRegistrationStateById(RegisterState::PendingSendRegistrationMail, $row["id"]); $mx_db->setRegistrationStateById(RegisterState::PendingSendRegistrationMail, $row["id"]);
} }
} else { } else {
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("Fehler beim Registrieren von " . $first_name . " " . $last_name . "."); $mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . ".");
$mxConn->send($config["register_room"], $mxMsg); $mxConn->send($config["register_room"], $mxMsg);
throw new Exception($language["REGISTRATION_FAILED"]); throw new Exception($language["REGISTRATION_FAILED"]);
} }
break; break;
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::RegistrationDeclined:
case RegisterState::AllDone: case RegisterState::AllDone:
// do reqular cleanup // do reqular cleanup
break; 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());
} }
} }
?> ?>

View File

@@ -1,65 +1,78 @@
<?php <?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.
*/
require_once("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");
} }
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
const PendingEmailVerify = 1;
// Sending a message to the register room failed on first attempt
const PendingAdminSend = 5;
// No admin has verified the registration yet
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?) // Sending an E-Mail failed in the first attempt. Will retry later
const PendingSendRegistrationMail = 8; const PendingEmailSend = 0;
// User got a mail. We wait for it to verfiy
const PendingEmailVerify = 1;
// Sending a message to the register room failed on first attempt
const PendingAdminSend = 5;
// No admin has verified the registration yet
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;
// 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;
/** private $db = NULL;
* Creates mxDatabase object
* @param config object which has following members: /**
* databaseURI: path to the sqlite file where the credentials should be stored * Creates mxDatabase object
* or a param which can be used to connect to a database with PDO * @param config object which has following members:
* databaseUser and databasePass when authentication is required * databaseURI: path to the sqlite file where the credentials should be stored
* register_email which email does the register bot have (here used for providing lookup) * or a param which can be used to connect to a database with PDO
*/ * databaseUser and databasePass when authentication is required
function __construct($config) { * register_email which email does the register bot have (here used for providing lookup)
if (empty($config)) { */
throw new Exception("config is empty"); function __construct($config) {
} if (empty($config)) {
if (!isset($config["databaseURI"])) { throw new Exception("config is empty");
throw new Exception("'databaseURI' not defined"); }
} if (!isset($config["databaseURI"])) {
$db_input = $config["databaseURI"]; throw new Exception("'databaseURI' not defined");
$user = ''; }
$password = ''; $db_input = $config["databaseURI"];
if (isset($config["databaseUser"]) && isset($config["databasePass"])) { $user = '';
// only use it when both are defined $password = '';
$user = $config["databaseUser"]; if (isset($config["databaseUser"]) && isset($config["databasePass"])) {
$password = $config["databasePass"]; // only use it when both are defined
} $user = $config["databaseUser"];
// create database file when not existent yet $password = $config["databasePass"];
$this->db = new PDO($db_input, $user, $password); }
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // create database file when not existent yet
$this->db->exec("CREATE TABLE IF NOT EXISTS registrations( $this->db = new PDO($db_input, $user, $password);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->exec("CREATE TABLE IF NOT EXISTS registrations(
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
state INT DEFAULT 0, state INT DEFAULT 0,
first_name TEXT, first_name TEXT,
@@ -72,7 +85,7 @@ class mxDatabase
admin_token TEXT, admin_token TEXT,
request_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP request_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)"); )");
$this->db->exec("CREATE TABLE IF NOT EXISTS logins ( $this->db->exec("CREATE TABLE IF NOT EXISTS logins (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
active INT DEFAULT 1, active INT DEFAULT 1,
first_name TEXT, first_name TEXT,
@@ -83,257 +96,273 @@ class mxDatabase
create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)"); )");
// 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", $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));
fclose($myfile); fclose($myfile);
} }
// set writeable when not set already // set writeable when not set already
if (strpos($db_input, "sqlite") === 0) { if (strpos($db_input, "sqlite") === 0) {
$sqlite_file = substr($db_input, strlen("sqlite:")); $sqlite_file = substr($db_input, strlen("sqlite:"));
if (!is_writable($sqlite_file)) { if (!is_writable($sqlite_file)) {
chmod($sqlite_file, 0660); chmod($sqlite_file, 0660);
} }
unset($sqlite_file); unset($sqlite_file);
} }
} }
/** /**
* WARNING: This allows accessing the database directly. * WARNING: This allows accessing the database directly.
* This was only be added for convenience. You are advised to not use this function extensively * This was only be added for convenience. You are advised to not use this function extensively
* *
* @param sql String wich will be passed directly to the database * @param sql String wich will be passed directly to the database
* @return Response of PDO::query() * @return Response of PDO::query()
*/ */
function query($sql) { function query($sql) {
return $this->db->query($sql); return $this->db->query($sql);
} }
function setRegistrationStateVerify($state, $token) { function setRegistrationStateVerify($state, $token) {
$sql = "UPDATE registrations SET state = " . $state $sql = "UPDATE registrations SET state = " . $state
. " WHERE verify_token = '" . $token . "';"; . " WHERE verify_token = '" . $token . "';";
return $this->db->exec($sql); return $this->db->exec($sql);
} }
function setRegistrationStateById($state, $id) { function setRegistrationStateById($state, $id) {
$sql = "UPDATE registrations SET state = " . $state $sql = "UPDATE registrations SET state = " . $state
. " WHERE id = '" . $id . "';"; . " WHERE id = '" . $id . "';";
return $this->db->exec($sql); return $this->db->exec($sql);
} }
function setRegistrationStateAdmin($state, $token) { function setRegistrationStateAdmin($state, $token) {
$sql = "UPDATE registrations SET state = " . $state $sql = "UPDATE registrations SET state = " . $state
. " WHERE admin_token = '" . $token . "';"; . " WHERE admin_token = '" . $token . "';";
return $this->db->exec($sql); return $this->db->exec($sql);
} }
function setRegistrationState($state, $token) { function setRegistrationState($state, $token) {
$sql = "UPDATE registrations SET state = " . $state $sql = "UPDATE registrations SET state = " . $state
. " WHERE verify_token = '" . $token . "' OR admin_token = '" . $token . "';"; . " WHERE verify_token = '" . $token . "' OR admin_token = '" . $token . "';";
return $this->db->exec($sql); return $this->db->exec($sql);
} }
function userPendingRegistrations($username) { function userPendingRegistrations($username) {
$sql = "SELECT COUNT(*) FROM registrations WHERE username = '" . $username . "' AND NOT state = " $sql = "SELECT COUNT(*) FROM registrations WHERE username = '" . $username . "' AND NOT state = "
. RegisterState::RegistrationDeclined . " LIMIT 1;"; . RegisterState::RegistrationDeclined . " LIMIT 1;";
$res = $this->db->query($sql); $res = $this->db->query($sql);
if ($res->fetchColumn() > 0) { if ($res->fetchColumn() > 0) {
return true; return true;
} }
return false; return false;
} }
function userRegistered($username) {
$sql = "SELECT COUNT(*) FROM logins WHERE localpart = '" . $username . "' LIMIT 1;";
$res = $this->db->query($sql);
if ($res->fetchColumn() > 0) {
return true;
}
return false;
}
/** function userRegistered($username) {
* Adds user to the database. Next steps should be sending a verify-mail to the user $sql = "SELECT COUNT(*) FROM logins WHERE localpart = '" . $username . "' LIMIT 1;";
* @param first_name First name of the user $res = $this->db->query($sql);
* @param last_name Sirname of the user if ($res->fetchColumn() > 0) {
* @param username the future localpart of that user return true;
* @param note Note the user typed in to give a hint }
* @param email E-Mail-Adress which will be stored into the database. return false;
* This will be send to the server on first login }
*
* @return ["verify_token"]
*/
function addRegistration($first_name, $last_name, $username, $note, $email) {
if ($this->userPendingRegistrations($username)) {
require_once("language.php");
throw new Exception($language["USERNAME_PENDING_REGISTRATION"]." (requested)");
}
if ($this->userRegistered($username)) {
require_once("language.php");
throw new Exception($language["USERNAME_REGISTERED"] . " (registered)");
}
$verify_token = bin2hex(random_bytes(16)); /**
$admin_token = bin2hex(random_bytes(16)); * Adds user to the database. Next steps should be sending a verify-mail to the user
* @param first_name First name of the user
* @param last_name Sirname of the user
* @param username the future localpart of that user
* @param note Note the user typed in to give a hint
* @param email E-Mail-Adress which will be stored into the database.
* This will be send to the server on first login
*
* @return ["verify_token"]
*/
function addRegistration($first_name, $last_name, $username, $note, $email) {
if ($this->userPendingRegistrations($username)) {
throw new Exception("USERNAME_PENDING_REGISTRATION");
}
if ($this->userRegistered($username)) {
throw new Exception("USERNAME_REGISTERED");
}
$this->db->exec("INSERT INTO registrations $verify_token = bin2hex(random_bytes(16));
$admin_token = bin2hex(random_bytes(16));
$this->db->exec("INSERT INTO registrations
(first_name, last_name, username, note, email, verify_token, admin_token) (first_name, last_name, username, note, email, verify_token, admin_token)
VALUES ('" . $first_name."','" . $last_name . "','" . $username . "','" . $note . "','" VALUES ('" . $first_name . "','" . $last_name . "','" . $username . "','" . $note . "','"
. $email."','" .$verify_token."','" .$admin_token."')"); . $email . "','" . $verify_token . "','" . $admin_token . "')");
return [ return [
"verify_token"=> $verify_token, "verify_token" => $verify_token,
]; ];
} }
/** /**
* Gets the user for the verify_admin page. * Gets the user for the verify_admin page.
* *
* @return ArrayOfUser|NULL Array with "first_name, last_name, username, note and email" * @return ArrayOfUser|NULL Array with "first_name, last_name, username, note and email"
* as members * as members
*/ */
function getUserForApproval($admin_token) { function getUserForApproval($admin_token) {
$sql = "SELECT COUNT(*) FROM registrations WHERE admin_token = '" . $admin_token . "'" $sql = "SELECT COUNT(*) FROM registrations WHERE admin_token = '" . $admin_token . "'"
. " AND state = " . RegisterState::PendingAdminVerify . " LIMIT 1;"; . " AND state = " . RegisterState::PendingAdminVerify . " LIMIT 1;";
$res = $this->db->query($sql); $res = $this->db->query($sql);
$first_name = NULL; $last_name = NULL; $username = NULL; $note = NULL; $email = NULL;
if ($res->fetchColumn() > 0) { if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, username, 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;";
foreach ($this->db->query($sql) as $row) { foreach ($this->db->query($sql) as $row) {
// will only be executed once // will only be executed once
return $row; return $row;
} }
} }
return NULL; return NULL;
} }
/** /**
* Gets the user when it opens the page to verify its mail * Gets the user when it opens the page to verify its mail
* *
* @return ArrayOfUser|NULL Array with "first_name, last_name, note, email and admin_token" * @return ArrayOfUser|NULL Array with "first_name, last_name, note, email and admin_token"
* as members * as members
*/ */
function getUserForVerify($verify_token) { function getUserForVerify($verify_token) {
$sql = "SELECT COUNT(*) FROM registrations WHERE verify_token = '" . $verify_token . "'" $sql = "SELECT COUNT(*) FROM registrations WHERE verify_token = '" . $verify_token . "'"
. " AND state = " . RegisterState::PendingEmailVerify . " LIMIT 1;"; . " AND state = " . RegisterState::PendingEmailVerify . " LIMIT 1;";
$res = $this->db->query($sql); $res = $this->db->query($sql);
$first_name = NULL; $last_name = NULL; $username = NULL; $note = NULL; $email = NULL;
if ($res->fetchColumn() > 0) { if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, note, email, admin_token FROM registrations " $sql = "SELECT first_name, last_name, note, email, admin_token FROM registrations "
. " WHERE verify_token = '" . $verify_token . "'" . " WHERE verify_token = '" . $verify_token . "'"
. " AND state = " . RegisterState::PendingEmailVerify . " LIMIT 1;"; . " AND state = " . RegisterState::PendingEmailVerify . " LIMIT 1;";
foreach ($this->db->query($sql) as $row) { foreach ($this->db->query($sql) as $row) {
// will only be executed once // will only be executed once
return $row; return $row;
} }
} }
return NULL; return NULL;
} }
function getUserForLogin($localpart, $password) { function getUserForLogin($localpart, $password) {
$sql = "SELECT COUNT(*) FROM logins WHERE localpart = '" . $localpart $sql = "SELECT COUNT(*) FROM logins WHERE localpart = '" . $localpart
. "' AND active = 1 LIMIT 1;"; . "' AND active = 1 LIMIT 1;";
$res = $this->db->query($sql); $res = $this->db->query($sql);
if ($res->fetchColumn() > 0) { if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, email, password_hash FROM logins " $sql = "SELECT first_name, last_name, email, password_hash FROM logins "
. " WHERE localpart = '" . $localpart . "' AND active = 1 LIMIT 1;"; . " WHERE localpart = '" . $localpart . "' AND active = 1 LIMIT 1;";
foreach ($this->db->query($sql) as $row) { foreach ($this->db->query($sql) as $row) {
if (password_verify($password, $row["password_hash"])) { if (password_verify($password, $row["password_hash"])) {
return $row; return $row;
} }
} }
} }
return NULL; return NULL;
} }
/** /**
* adds User to be able to login afterwards. * adds User to be able to login afterwards.
* @param first_name First name of the user * @param first_name First name of the user
* @param last_name Sirname of the user * @param last_name Sirname of the user
* @param username the future localpart of that user * @param username the future localpart of that user
* @param email E-Mail-Adress which will be stored into the database. * @param email E-Mail-Adress which will be stored into the database.
* This will be send to the server on first login * This will be send to the server on first login
* *
* @return password|NULL with member password as this method generates a * @return password|NULL with member password as this method generates a
* password and saves that into the database * password and saves that into the database
* NULL when failed * NULL when failed
* *
*/ */
function addUser($first_name, $last_name, $username, $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;
} }
// 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 "
. "('" . $first_name."','" . $last_name . "','" . $username . "','" . "('" . $first_name . "','" . $last_name . "','" . $username . "','"
. $password_hash . "','" . $email . "');"; . $password_hash . "','" . $email . "');";
if ($this->db->exec($sql)) { if ($this->db->exec($sql)) {
return $password; return $password;
} }
return NULL; return NULL;
} }
function searchUserByName($search_term) { function updatePassword($localpart, $old_password, $new_password) {
$term = filter_var($search_term, FILTER_SANITIZE_STRING); $user = $this->getUserForLogin($localpart, $old_password);
$result = array(); if ($user == NULL) {
$sql = "SELECT COUNT(*) FROM logins WHERE" throw new Exception("user with that credentials not found");
. " localpart LIKE '" . $term . "%' AND active = 1;"; }
$res = $this->db->query($sql);
if ($res->fetchColumn() > 0) { // The credentials were fine. So now set the new password
$sql = "SELECT first_name, last_name, localpart FROM logins WHERE" $password_hash = password_hash($new_password, PASSWORD_BCRYPT, ["cost" => 12]);
. " localpart LIKE '" . $term . "%' AND active = 1;";
foreach ($this->db->query($sql) as $row) {
array_push($result, [
"display_name" => $row["first_name"] . " " . $row["last_name"],
"user_id" => $row["localpart"],
]);
}
}
return $result;
}
function searchUserByEmail($search_term) { $sql = "UPDATE logins SET password_hash = '" . $password_hash . "'"
$term = filter_var($search_term, FILTER_SANITIZE_STRING); . "WHERE localpart = '" . $localpart . "'";
$result = array();
$sql = "SELECT COUNT(*) FROM logins WHERE" if ($this->db->exec($sql)) {
. " email = '" . $term . "' AND active = 1;"; return true;
$res = $this->db->query($sql); }
return false;
}
function searchUserByName($search_term) {
$term = filter_var($search_term, FILTER_SANITIZE_STRING);
$result = array();
$sql = "SELECT COUNT(*) FROM logins WHERE"
. " localpart LIKE '" . $term . "%' AND active = 1;";
$res = $this->db->query($sql);
if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, localpart FROM logins WHERE"
. " localpart LIKE '" . $term . "%' AND active = 1;";
foreach ($this->db->query($sql) as $row) {
array_push($result, [
"display_name" => $row["first_name"] . " " . $row["last_name"],
"user_id" => $row["localpart"],
]);
}
}
return $result;
}
function searchUserByEmail($search_term) {
$term = filter_var($search_term, FILTER_SANITIZE_STRING);
$result = array();
$sql = "SELECT COUNT(*) FROM logins WHERE"
. " email = '" . $term . "' AND active = 1;";
$res = $this->db->query($sql);
if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, localpart FROM logins WHERE"
. " email = '" . $term . "' AND active = 1;";
foreach ($this->db->query($sql) as $row) {
array_push($result, [
"display_name" => $row["first_name"] . " " . $row["last_name"],
"user_id" => $row["localpart"],
]);
}
}
return $result;
}
if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, localpart FROM logins WHERE"
. " email = '" . $term . "' AND active = 1;";
foreach ($this->db->query($sql) as $row) {
array_push($result, [
"display_name" => $row["first_name"] . " " . $row["last_name"],
"user_id" => $row["localpart"],
]);
}
}
return $result;
}
} }
if (!isset($mx_db)) { if (!isset($mx_db)) {
$mx_db = new mxDatabase($config); $mx_db = new mxDatabase($config);
} }
?> ?>

33
helpers.php Normal file
View File

@@ -0,0 +1,33 @@
<?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);
if ($sepPos === false) {
// : not found. Assume mxid is localpart
// TODO: further checks
$localpart = $mxid;
} else {
$localpart = substr($mxid, 1, strpos($mxid, ':') - 1);
}
}
return $localpart;
}
?>

View File

@@ -1,6 +1,21 @@
<?php <?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.
*/
require_once("../database.php"); require_once("../database.php");
$response=[ $response = [
"limited" => false, "limited" => false,
"result" => [], "result" => [],
]; ];
@@ -9,7 +24,7 @@ try {
$inputJSON = file_get_contents('php://input'); $inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE); $input = json_decode($inputJSON, TRUE);
if (empty($input)) { if (empty($input)) {
throw new Exception('no valid json as input present'); throw new Exception('no valid json as input present');
} }
if (!isset($input["by"])) { if (!isset($input["by"])) {
throw new Exception('"by" is not defined'); throw new Exception('"by" is not defined');
@@ -25,9 +40,8 @@ try {
$response["result"] = $mx_db->searchUserByEmail($input["search_term"]); $response["result"] = $mx_db->searchUserByEmail($input["search_term"]);
break; break;
default: default:
throw new Exception("unknown type for \"by\" param"); throw new Exception('unknown type for "by" param');
} }
} catch (Exception $e) { } catch (Exception $e) {
error_log("failed with error: " . $e->getMessage()); error_log("failed with error: " . $e->getMessage());
$response["error"] = $e->getMessage(); $response["error"] = $e->getMessage();

View File

@@ -1,4 +1,19 @@
<?php <?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.
*/
require_once("../database.php"); require_once("../database.php");
$response = [ $response = [
"lookup" => [] "lookup" => []
@@ -7,7 +22,7 @@ try {
$inputJSON = file_get_contents('php://input'); $inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE); $input = json_decode($inputJSON, TRUE);
if (!isset($input)) { if (!isset($input)) {
throw new Exception('request body is no valid json'); throw new Exception('request body is no valid json');
} }
if (!isset($input["lookup"])) { if (!isset($input["lookup"])) {
@@ -23,26 +38,28 @@ try {
if (!isset($lookup["address"])) { if (!isset($lookup["address"])) {
throw new Exception('"lookup.address" is not defined'); throw new Exception('"lookup.address" is not defined');
} }
$res2 = array(); $res2 = NULL;
switch ($lookup["medium"]) { switch ($lookup["medium"]) {
case "email": case "email":
$res2 = $mx_db->searchUserByEmail($lookup["address"]); $res2 = $mx_db->searchUserByEmail($lookup["address"]);
if (!empty($res2)) { if (!empty($res2)) {
array_push($response["lookup"], [ array_push($response["lookup"], [
"medium" => $lookup["medium"], "medium" => $lookup["medium"],
"address" => $lookup["address"], "address" => $lookup["address"],
"id" => [ "id" => [
"type" => "localpart", "type" => "localpart",
"value" => $res2[0]["user_id"], "value" => $res2[0]["user_id"],
]
] ]
]
); );
} }
break; break;
case "msisdn": case "msisdn":
// This is reserved for number lookups
throw new Exception("unimplemented lookup medium");
break; break;
default: default:
throw new Exception("unknown type for \"by\" param"); throw new Exception("unknown lookup medium");
} }
} }
} catch (Exception $e) { } catch (Exception $e) {

View File

@@ -1,11 +1,26 @@
<?php <?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.
*/
require_once("../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');
$input = json_decode($inputJSON, TRUE); $input = json_decode($inputJSON, TRUE);
if (empty($input)) { if (empty($input)) {
throw new Exception('no valid json as input present'); throw new Exception('no valid json as input present');
} }
if (!isset($input["lookup"])) { if (!isset($input["lookup"])) {
throw new Exception('"lookup" is not defined'); throw new Exception('"lookup" is not defined');
@@ -16,7 +31,7 @@ try {
if (!isset($input["lookup"]["address"])) { if (!isset($input["lookup"]["address"])) {
throw new Exception('"lookup.address" is not defined'); throw new Exception('"lookup.address" is not defined');
} }
$res2 = array(); $res2 = NULL;
switch ($input["lookup"]["medium"]) { switch ($input["lookup"]["medium"]) {
case "email": case "email":
$res2 = $mx_db->searchUserByEmail($input["lookup"]["address"]); $res2 = $mx_db->searchUserByEmail($input["lookup"]["address"]);
@@ -32,15 +47,19 @@ try {
] ]
]; ];
} }
break;
case "msisdn":
// This is reserved for number lookups
throw new Exception("unimplemented lookup medium");
break; break;
default: default:
throw new Exception("unknown type for \"by\" param"); throw new Exception("unknown lookup medium");
} }
} catch (Exception $e) { } catch (Exception $e) {
error_log("ídentity_bulk failed with error: " . $e->getMessage()); error_log("ídentity_single failed with error: " . $e->getMessage());
$response["error"] = $e->getMessage(); $response = [
"error" => $e->getMessage()
];
} }
print (json_encode($response, JSON_PRETTY_PRINT) . "\n"); print (json_encode($response, JSON_PRETTY_PRINT) . "\n");
?> ?>

View File

@@ -0,0 +1,69 @@
<?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.
*/
// URL for this: /_matrix/client/r0/account/password?access_token=$ACCESS_TOKEN
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
print ("{}");
// return with success
exit();
}
$response = new stdClass;
try {
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);
if (empty($input)) {
throw new Exception('no valid json as input present');
}
if (!isset($input["auth"])) {
throw new Exception('"auth" is not defined');
}
if (!isset($input["auth"]["user"]) || !isset($input["auth"]["password"])) {
throw new Exception('"auth.user" or "auth.password" is not defined');
}
if (!isset($input["auth"]["type"]) || $input["auth"]["type"] !== "m.login.password") {
throw new Exception('no or unknown auth.type');
}
if (!isset($input["new_password"])) {
throw new Exception('"new_password" is not defined');
}
require_once("../helpers.php");
$localpart = stripLocalpart($input["auth"]["user"]);
if (empty($localpart)) {
throw new Exception("localpart cannot be identified");
}
require_once("../database.php");
if (!$mx_db->updatePassword(
$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());
$response = [
"errorcode" => "M_UNKNOWN",
"error" => $e->getMessage(),
];
}
print (json_encode($response, JSON_PRETTY_PRINT));
?>

View File

@@ -1,4 +1,19 @@
<?php <?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.
*/
$response = [ $response = [
"auth" => [ "auth" => [
"success" => false, "success" => false,
@@ -6,18 +21,21 @@ $response = [
]; ];
require_once("../database.php"); require_once("../database.php");
abstract class LoginRequester { abstract class LoginRequester {
const UNDEFINED = 0; const UNDEFINED = 0;
const MXISD = 1; const MXISD = 1;
const RestAuth = 2; const RestAuth = 2;
} }
$loginRequester = LoginRequester::UNDEFINED; $loginRequester = LoginRequester::UNDEFINED;
try { try {
$inputJSON = file_get_contents('php://input'); $inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE); $input = json_decode($inputJSON, TRUE);
$mxid = NULL; $mxid = $localpart = NULL;
$localpart = NULL;
if (isset($input["user"])) { if (isset($input["user"])) {
if (isset($input["user"]["localpart"])) { if (isset($input["user"]["localpart"])) {
$localpart = $input["user"]["localpart"]; $localpart = $input["user"]["localpart"];
@@ -31,32 +49,27 @@ try {
$mxid = $input["user"]["mxid"]; $mxid = $input["user"]["mxid"];
$loginRequester = LoginRequester::MXISD; $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 // 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) && !empty($mxid)) { if (empty($localpart)) {
// A mxid would start with an @ so we start at the 2. position require_once("../helpers.php");
$sepPos = strpos($mxid,':', 1); $localpart = stripLocalpart($mxid);
if ($sepPos === false) {
// : not found. Assume mxid is localpart
// TODO: further checks
$localpart = $mxid;
} else {
$localpart = substr($mxid, 1, strpos($mxid,':') - 1 );
}
} }
if (empty($localpart)) { if (empty($localpart)) {
throw new Exception ("localpart cannot be identified"); throw new Exception("localpart cannot be identified");
} }
$password = NULL; $password = NULL;
if (isset($input["user"]) && isset($input["user"]["password"])) { if (isset($input["user"]["password"])) {
$password = $input["user"]["password"]; $password = $input["user"]["password"];
} }
if (empty($password)) { if (empty($password)) {
throw new Exception ("password is not present"); throw new Exception("password is not present");
} }
$user = $mx_db->getUserForLogin($localpart, $password); $user = $mx_db->getUserForLogin($localpart, $password);
@@ -88,6 +101,7 @@ try {
// only return that it was successful. // only return that it was successful.
// we do not know how the data shall be transmitted so we do nothing with it // we do not know how the data shall be transmitted so we do nothing with it
$response["auth"]["success"] = false; $response["auth"]["success"] = false;
$response["auth"]["error"] = "unidentified requester";
break; break;
} }
} catch (Exception $e) { } catch (Exception $e) {

View File

@@ -1,4 +1,19 @@
<?php <?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.
*/
$language = array( $language = array(
"NO_CONFIGURATION" => "Es konnte keine Konfiguration gefunden werden.", "NO_CONFIGURATION" => "Es konnte keine Konfiguration gefunden werden.",
"UNKNOWN_SESSION" => "Sitzungstoken nicht vorhanden oder ungültig.", "UNKNOWN_SESSION" => "Sitzungstoken nicht vorhanden oder ungültig.",

View File

@@ -1,12 +1,27 @@
<?php <?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.
*/
$lang = "de-de"; $lang = "de-de";
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 = dirname(__FILE__) . "/lang/lang.".$lang.".php"; $lang_file = dirname(__FILE__) . "/lang/lang." . $lang . ".php";
if (!file_exists($lang_file)) { 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";
} }
require_once($lang_file); require_once($lang_file);
unset($lang_file); unset($lang_file);

View File

@@ -1,15 +1,29 @@
<?php <?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 send_mail($receiver, $subject, $body) { function send_mail($receiver, $subject, $body) {
include("config.php"); include("config.php");
$headers = "From: " . $config["register_email"] . "\r\n" $headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8"; . "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers); 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 . ",
Du hast anscheinend versucht dich auf $homeserver zu registrieren. Du hast anscheinend versucht dich auf $homeserver zu registrieren.
Hier gibt es eine zweistufige Registrierung. Hier gibt es eine zweistufige Registrierung.
@@ -26,12 +40,12 @@ 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) {
$subject = "Registrierung wartet auf Bestätigung durch Administratoren"; $subject = "Registrierung wartet auf Bestätigung durch Administratoren";
$body = "Guten Tag " . $user . ", $body = "Guten Tag " . $user . ",
Deine Registrierungsanfrage wurde verifiziert und wird nun durch die Administratoren überprüft. Deine Registrierungsanfrage wurde verifiziert und wird nun durch die Administratoren überprüft.
@@ -40,12 +54,12 @@ 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) {
$subject = "Registrierung auf $homeserver genehmigt."; $subject = "Registrierung auf $homeserver genehmigt.";
$body = "Guten Tag " . $user . ", $body = "Guten Tag " . $user . ",
Deine Registrierungsanfrage wurde durch die Administratoren bestätigt. Deine Registrierungsanfrage wurde durch die Administratoren bestätigt.
@@ -54,13 +68,12 @@ Wir hoffen, das Problem ist bald behoben.
Wir melden uns, wenn die Registrierung erfolgreich war. 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) {
$subject = "Registrierung auf $homeserver erfolgreich."; $subject = "Registrierung auf $homeserver erfolgreich.";
$body = "Guten Tag " . $user . ", $body = "Guten Tag " . $user . ",
Deine Registrierungsanfrage wurde durch die Administratoren bestätigt. Deine Registrierungsanfrage wurde durch die Administratoren bestätigt.
@@ -68,41 +81,42 @@ Zum Anmelden kannst du folgende Zugangsdaten verwenden:
Nutzername: $username Nutzername: $username
Passwort: $password Passwort: $password
Hinweis: Aktuell ist es nicht möglich, das Passwort selbst zu ändern. Sobald die Funktionalität zur Hinweis: Das Passwort kannst du aktuell über die App selbst ändern. Auch wenn das Passwort nirgends
Verfügung steht, gibt es aber einen Hinweis. 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 . ",
Deine Registrierungsanfrage wurde durch die Administratoren abgelehnt.\n"; Deine Registrierungsanfrage wurde durch die Administratoren abgelehnt.\n";
if (empty($reason)) { if (empty($reason)) {
$body .= "\nEs wurde kein Grund angegeben\n"; $body .= "\nEs wurde kein Grund angegeben\n";
} else { } else {
$body .= "\nAls Grund wurde folgendes angegeben:\n$reason\n"; $body .= "\nAls Grund wurde folgendes angegeben:\n$reason\n";
} }
$body .= "\nDas Administratoren-Team von " . $homeserver; $body .= "\nDas Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body ); return send_mail($receiver, $subject, $body);
} }
?> ?>

View File

@@ -1,6 +1,18 @@
<html> <html><head><?php
<head> /**
<?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.
*/
require_once "../language.php"; require_once "../language.php";
if (!file_exists("../config.php")) { if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]); print($language["NO_CONFIGURATION"]);
@@ -20,32 +32,32 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
try { try {
if (!isset($_SESSION["token"]) || !isset($_POST["token"]) || $_SESSION["token"] != $_POST["token"]) { if (!isset($_SESSION["token"]) || !isset($_POST["token"]) || $_SESSION["token"] != $_POST["token"]) {
// token not present or invalid // token not present or invalid
throw new Exception($language["UNKNOWN_SESSION"]); throw new Exception("UNKNOWN_SESSION");
} }
if (!isset($_POST["username"])) { if (!isset($_POST["username"])) {
throw new Exception($language["UNKNOWN_USERNAME"]); throw new Exception("UNKNOWN_USERNAME");
} }
if (strlen($_POST["username"] > 20 || strlen($_POST["username"]) < 3)) { if (strlen($_POST["username"] > 20 || strlen($_POST["username"]) < 3)) {
throw new Exception($language["USERNAME_LENGTH_INVALID"]); throw new Exception("USERNAME_LENGTH_INVALID");
} }
if (ctype_alnum($_POST['username']) != true) { if (ctype_alnum($_POST['username']) != true) {
throw new Exception($language["USERNAME_NOT_ALNUM"]); throw new Exception("USERNAME_NOT_ALNUM");
} }
if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"] && if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"] &&
$_POST["password"] != $_POST["password_confirm"]) { $_POST["password"] != $_POST["password_confirm"]) {
throw new Exception($language["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) {
throw new Exception($language["NOTE_LENGTH_EXEEDED"]); throw new Exception("NOTE_LENGTH_EXEEDED");
} }
if (!isset($_POST["email"]) || !filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) { if (!isset($_POST["email"]) || !filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
throw new Exception($language["EMAIL_INVALID_FORMAT"]); throw new Exception("EMAIL_INVALID_FORMAT");
} }
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($language["FIRSTNAME_INVALID_FORMAT"]); 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($language["SIRNAME_INVALID_FORMAT"]); throw new Exception("SIRNAME_INVALID_FORMAT");
} }
$first_name = filter_var($_POST["first_name"], FILTER_SANITIZE_STRING); $first_name = filter_var($_POST["first_name"], FILTER_SANITIZE_STRING);
@@ -87,7 +99,11 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
print("<title>" . $language["REGISTRATION_REQUEST_FAILED"] . "</title>"); print("<title>" . $language["REGISTRATION_REQUEST_FAILED"] . "</title>");
print("</head><body>"); print("</head><body>");
print("<h1>" . $language["REGISTRATION_REQUEST_FAILED"] . "</h1>"); print("<h1>" . $language["REGISTRATION_REQUEST_FAILED"] . "</h1>");
print("<p>" . $e->getMessage() . "</p>"); if (isset($language[$e->getMessage()])) {
print("<p>" . $language[$e->getMessage()] . "</p>");
} else {
print("<p>" . $e->getMessage() . "</p>");
}
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>"); print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
} }
} else { } else {

View File

@@ -1,6 +1,18 @@
<html> <html><head><?php
<head> /**
<?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.
*/
require_once "../language.php"; require_once "../language.php";
if (!file_exists("../config.php")) { if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]); print($language["NO_CONFIGURATION"]);
@@ -22,7 +34,7 @@ try {
throw new Exception("Method not allowed"); throw new Exception("Method not allowed");
} }
if (!isset($_GET["t"])) { if (!isset($_GET["t"])) {
throw new Exception($language["UNKNOWN_TOKEN"]); throw new Exception("UNKNOWN_TOKEN");
} }
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING); $token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
@@ -30,7 +42,7 @@ try {
$user = $mx_db->getUserForVerify($token); $user = $mx_db->getUserForVerify($token);
if ($user == NULL) { if ($user == NULL) {
throw new Exception($language["UNKNOWN_TOKEN"]); throw new Exception("UNKNOWN_TOKEN");
} }
$first_name = $user["first_name"]; $first_name = $user["first_name"];
$last_name = $user["last_name"]; $last_name = $user["last_name"];
@@ -69,7 +81,11 @@ try {
print("<title>" . $language["VERIFICATION_FAILED"] . "</title>"); print("<title>" . $language["VERIFICATION_FAILED"] . "</title>");
print("</head><body>"); print("</head><body>");
print("<h1>" . $language["VERIFICATION_FAILED"] . "</h1>"); print("<h1>" . $language["VERIFICATION_FAILED"] . "</h1>");
print("<p>" . $e->getMessage() . "</p>"); if (isset($language[$e->getMessage()])) {
print("<p>" . $language[$e->getMessage()] . "</p>");
} else {
print("<p>" . $e->getMessage() . "</p>");
}
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>"); print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
} }
?> ?>

View File

@@ -1,6 +1,18 @@
<html> <html><head><?php
<head> /**
<?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.
*/
require_once "../language.php"; require_once "../language.php";
if (!file_exists("../config.php")) { if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]); print($language["NO_CONFIGURATION"]);
@@ -22,7 +34,7 @@ try {
throw new Exception("Method not allowed"); throw new Exception("Method not allowed");
} }
if (!isset($_GET["t"])) { if (!isset($_GET["t"])) {
throw new Exception($language["UNKNOWN_TOKEN"]); throw new Exception("UNKNOWN_TOKEN");
} }
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING); $token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
@@ -42,7 +54,7 @@ try {
$user = $mx_db->getUserForApproval($token); $user = $mx_db->getUserForApproval($token);
if ($user == NULL) { if ($user == NULL) {
throw new Exception($language["UNKNOWN_TOKEN"]); throw new Exception("UNKNOWN_TOKEN");
} }
$first_name = $user["first_name"]; $first_name = $user["first_name"];
@@ -74,7 +86,7 @@ try {
$mxMsg->set_type("m.text"); $mxMsg->set_type("m.text");
$mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . "."); $mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . ".");
$mxConn->send($config["register_room"], $mxMsg); $mxConn->send($config["register_room"], $mxMsg);
throw new Exception($language["REGISTRATION_FAILED"]); throw new Exception("REGISTRATION_FAILED");
} }
print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>"); print("<title>" . $language["ADMIN_VERIFY_SITE_TITLE"] . "</title>");
@@ -160,7 +172,11 @@ background: rgba(255, 255, 255, 0.8);
print("<title>" . $language["REGISTRATION_FAILED"] . "</title>"); print("<title>" . $language["REGISTRATION_FAILED"] . "</title>");
print("</head><body>"); print("</head><body>");
print("<h1>" . $language["REGISTRATION_FAILED"] . "</h1>"); print("<h1>" . $language["REGISTRATION_FAILED"] . "</h1>");
print("<p>" . $e->getMessage() . "</p>"); if (isset($language[$e->getMessage()])) {
print("<p>" . $language[$e->getMessage()] . "</p>");
} else {
print("<p>" . $e->getMessage() . "</p>");
}
print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>"); print("<a href=\"" . $config["webroot"] . "/index.php" . "\">Zur Registrierungsseite</a>");
} }
?> ?>