added a forgotten password page
This commit is contained in:
parent
d40b4d6754
commit
9691de3b8f
@ -190,6 +190,6 @@ a {
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#register-email {
|
#register-email, #lost-email {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,7 @@
|
|||||||
"dbname": "db",
|
"dbname": "db",
|
||||||
"user": "user",
|
"user": "user",
|
||||||
"password": "pass",
|
"password": "pass",
|
||||||
"kind": "mysql"
|
"kind": "mysql",
|
||||||
|
"gmail_username":"example@gmail.com",
|
||||||
|
"gmail_password": "myawesomepassword123"
|
||||||
}
|
}
|
39
assets/php/phpmailer/Exception.php
Normal file
39
assets/php/phpmailer/Exception.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPMailer Exception class.
|
||||||
|
* PHP Version 5.5.
|
||||||
|
*
|
||||||
|
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||||
|
*
|
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||||
|
* @author Brent R. Matzelle (original founder)
|
||||||
|
* @copyright 2012 - 2017 Marcus Bointon
|
||||||
|
* @copyright 2010 - 2012 Jim Jagielski
|
||||||
|
* @copyright 2004 - 2009 Andy Prevost
|
||||||
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||||
|
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PHPMailer\PHPMailer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPMailer exception handler.
|
||||||
|
*
|
||||||
|
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||||
|
*/
|
||||||
|
class Exception extends \Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Prettify error message output.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function errorMessage()
|
||||||
|
{
|
||||||
|
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n";
|
||||||
|
}
|
||||||
|
}
|
138
assets/php/phpmailer/OAuth.php
Normal file
138
assets/php/phpmailer/OAuth.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPMailer - PHP email creation and transport class.
|
||||||
|
* PHP Version 5.5.
|
||||||
|
*
|
||||||
|
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||||
|
*
|
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||||
|
* @author Brent R. Matzelle (original founder)
|
||||||
|
* @copyright 2012 - 2015 Marcus Bointon
|
||||||
|
* @copyright 2010 - 2012 Jim Jagielski
|
||||||
|
* @copyright 2004 - 2009 Andy Prevost
|
||||||
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||||
|
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PHPMailer\PHPMailer;
|
||||||
|
|
||||||
|
use League\OAuth2\Client\Grant\RefreshToken;
|
||||||
|
use League\OAuth2\Client\Provider\AbstractProvider;
|
||||||
|
use League\OAuth2\Client\Token\AccessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth - OAuth2 authentication wrapper class.
|
||||||
|
* Uses the oauth2-client package from the League of Extraordinary Packages.
|
||||||
|
*
|
||||||
|
* @see http://oauth2-client.thephpleague.com
|
||||||
|
*
|
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||||
|
*/
|
||||||
|
class OAuth
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* An instance of the League OAuth Client Provider.
|
||||||
|
*
|
||||||
|
* @var AbstractProvider
|
||||||
|
*/
|
||||||
|
protected $provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current OAuth access token.
|
||||||
|
*
|
||||||
|
* @var AccessToken
|
||||||
|
*/
|
||||||
|
protected $oauthToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user's email address, usually used as the login ID
|
||||||
|
* and also the from address when sending email.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $oauthUserEmail = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client secret, generated in the app definition of the service you're connecting to.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $oauthClientSecret = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client ID, generated in the app definition of the service you're connecting to.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $oauthClientId = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The refresh token, used to obtain new AccessTokens.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $oauthRefreshToken = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth constructor.
|
||||||
|
*
|
||||||
|
* @param array $options Associative array containing
|
||||||
|
* `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
|
||||||
|
*/
|
||||||
|
public function __construct($options)
|
||||||
|
{
|
||||||
|
$this->provider = $options['provider'];
|
||||||
|
$this->oauthUserEmail = $options['userName'];
|
||||||
|
$this->oauthClientSecret = $options['clientSecret'];
|
||||||
|
$this->oauthClientId = $options['clientId'];
|
||||||
|
$this->oauthRefreshToken = $options['refreshToken'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new RefreshToken.
|
||||||
|
*
|
||||||
|
* @return RefreshToken
|
||||||
|
*/
|
||||||
|
protected function getGrant()
|
||||||
|
{
|
||||||
|
return new RefreshToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new AccessToken.
|
||||||
|
*
|
||||||
|
* @return AccessToken
|
||||||
|
*/
|
||||||
|
protected function getToken()
|
||||||
|
{
|
||||||
|
return $this->provider->getAccessToken(
|
||||||
|
$this->getGrant(),
|
||||||
|
['refresh_token' => $this->oauthRefreshToken]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a base64-encoded OAuth token.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getOauth64()
|
||||||
|
{
|
||||||
|
// Get a new token if it's not available or has expired
|
||||||
|
if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
|
||||||
|
$this->oauthToken = $this->getToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64_encode(
|
||||||
|
'user=' .
|
||||||
|
$this->oauthUserEmail .
|
||||||
|
"\001auth=Bearer " .
|
||||||
|
$this->oauthToken .
|
||||||
|
"\001\001"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
4770
assets/php/phpmailer/PHPMailer.php
Normal file
4770
assets/php/phpmailer/PHPMailer.php
Normal file
File diff suppressed because it is too large
Load Diff
419
assets/php/phpmailer/POP3.php
Normal file
419
assets/php/phpmailer/POP3.php
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPMailer POP-Before-SMTP Authentication Class.
|
||||||
|
* PHP Version 5.5.
|
||||||
|
*
|
||||||
|
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||||
|
*
|
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||||
|
* @author Brent R. Matzelle (original founder)
|
||||||
|
* @copyright 2012 - 2019 Marcus Bointon
|
||||||
|
* @copyright 2010 - 2012 Jim Jagielski
|
||||||
|
* @copyright 2004 - 2009 Andy Prevost
|
||||||
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||||
|
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PHPMailer\PHPMailer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPMailer POP-Before-SMTP Authentication Class.
|
||||||
|
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
|
||||||
|
* 1) This class does not support APOP authentication.
|
||||||
|
* 2) Opening and closing lots of POP3 connections can be quite slow. If you need
|
||||||
|
* to send a batch of emails then just perform the authentication once at the start,
|
||||||
|
* and then loop through your mail sending script. Providing this process doesn't
|
||||||
|
* take longer than the verification period lasts on your POP3 server, you should be fine.
|
||||||
|
* 3) This is really ancient technology; you should only need to use it to talk to very old systems.
|
||||||
|
* 4) This POP3 class is deliberately lightweight and incomplete, implementing just
|
||||||
|
* enough to do authentication.
|
||||||
|
* If you want a more complete class there are other POP3 classes for PHP available.
|
||||||
|
*
|
||||||
|
* @author Richard Davey (original author) <rich@corephp.co.uk>
|
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
class POP3
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The POP3 PHPMailer Version number.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const VERSION = '6.1.3';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default POP3 port number.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const DEFAULT_PORT = 110;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default timeout in seconds.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const DEFAULT_TIMEOUT = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug display level.
|
||||||
|
* Options: 0 = no, 1+ = yes.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $do_debug = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POP3 mail server hostname.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POP3 port number.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POP3 Timeout Value in seconds.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $tval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POP3 username.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POP3 password.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource handle for the POP3 connection socket.
|
||||||
|
*
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
protected $pop_conn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we connected?
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $connected = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error container.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $errors = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Line break constant.
|
||||||
|
*/
|
||||||
|
const LE = "\r\n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple static wrapper for all-in-one POP before SMTP.
|
||||||
|
*
|
||||||
|
* @param string $host The hostname to connect to
|
||||||
|
* @param int|bool $port The port number to connect to
|
||||||
|
* @param int|bool $timeout The timeout value
|
||||||
|
* @param string $username
|
||||||
|
* @param string $password
|
||||||
|
* @param int $debug_level
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function popBeforeSmtp(
|
||||||
|
$host,
|
||||||
|
$port = false,
|
||||||
|
$timeout = false,
|
||||||
|
$username = '',
|
||||||
|
$password = '',
|
||||||
|
$debug_level = 0
|
||||||
|
) {
|
||||||
|
$pop = new self();
|
||||||
|
|
||||||
|
return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate with a POP3 server.
|
||||||
|
* A connect, login, disconnect sequence
|
||||||
|
* appropriate for POP-before SMTP authorisation.
|
||||||
|
*
|
||||||
|
* @param string $host The hostname to connect to
|
||||||
|
* @param int|bool $port The port number to connect to
|
||||||
|
* @param int|bool $timeout The timeout value
|
||||||
|
* @param string $username
|
||||||
|
* @param string $password
|
||||||
|
* @param int $debug_level
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
|
||||||
|
{
|
||||||
|
$this->host = $host;
|
||||||
|
// If no port value provided, use default
|
||||||
|
if (false === $port) {
|
||||||
|
$this->port = static::DEFAULT_PORT;
|
||||||
|
} else {
|
||||||
|
$this->port = (int) $port;
|
||||||
|
}
|
||||||
|
// If no timeout value provided, use default
|
||||||
|
if (false === $timeout) {
|
||||||
|
$this->tval = static::DEFAULT_TIMEOUT;
|
||||||
|
} else {
|
||||||
|
$this->tval = (int) $timeout;
|
||||||
|
}
|
||||||
|
$this->do_debug = $debug_level;
|
||||||
|
$this->username = $username;
|
||||||
|
$this->password = $password;
|
||||||
|
// Reset the error log
|
||||||
|
$this->errors = [];
|
||||||
|
// connect
|
||||||
|
$result = $this->connect($this->host, $this->port, $this->tval);
|
||||||
|
if ($result) {
|
||||||
|
$login_result = $this->login($this->username, $this->password);
|
||||||
|
if ($login_result) {
|
||||||
|
$this->disconnect();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We need to disconnect regardless of whether the login succeeded
|
||||||
|
$this->disconnect();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to a POP3 server.
|
||||||
|
*
|
||||||
|
* @param string $host
|
||||||
|
* @param int|bool $port
|
||||||
|
* @param int $tval
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function connect($host, $port = false, $tval = 30)
|
||||||
|
{
|
||||||
|
// Are we already connected?
|
||||||
|
if ($this->connected) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
|
||||||
|
//Rather than suppress it with @fsockopen, capture it cleanly instead
|
||||||
|
set_error_handler([$this, 'catchWarning']);
|
||||||
|
|
||||||
|
if (false === $port) {
|
||||||
|
$port = static::DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to the POP3 server
|
||||||
|
$this->pop_conn = fsockopen(
|
||||||
|
$host, // POP3 Host
|
||||||
|
$port, // Port #
|
||||||
|
$errno, // Error Number
|
||||||
|
$errstr, // Error Message
|
||||||
|
$tval
|
||||||
|
); // Timeout (seconds)
|
||||||
|
// Restore the error handler
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
// Did we connect?
|
||||||
|
if (false === $this->pop_conn) {
|
||||||
|
// It would appear not...
|
||||||
|
$this->setError(
|
||||||
|
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increase the stream time-out
|
||||||
|
stream_set_timeout($this->pop_conn, $tval, 0);
|
||||||
|
|
||||||
|
// Get the POP3 server response
|
||||||
|
$pop3_response = $this->getResponse();
|
||||||
|
// Check for the +OK
|
||||||
|
if ($this->checkResponse($pop3_response)) {
|
||||||
|
// The connection is established and the POP3 server is talking
|
||||||
|
$this->connected = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log in to the POP3 server.
|
||||||
|
* Does not support APOP (RFC 2828, 4949).
|
||||||
|
*
|
||||||
|
* @param string $username
|
||||||
|
* @param string $password
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function login($username = '', $password = '')
|
||||||
|
{
|
||||||
|
if (!$this->connected) {
|
||||||
|
$this->setError('Not connected to POP3 server');
|
||||||
|
}
|
||||||
|
if (empty($username)) {
|
||||||
|
$username = $this->username;
|
||||||
|
}
|
||||||
|
if (empty($password)) {
|
||||||
|
$password = $this->password;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the Username
|
||||||
|
$this->sendString("USER $username" . static::LE);
|
||||||
|
$pop3_response = $this->getResponse();
|
||||||
|
if ($this->checkResponse($pop3_response)) {
|
||||||
|
// Send the Password
|
||||||
|
$this->sendString("PASS $password" . static::LE);
|
||||||
|
$pop3_response = $this->getResponse();
|
||||||
|
if ($this->checkResponse($pop3_response)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect from the POP3 server.
|
||||||
|
*/
|
||||||
|
public function disconnect()
|
||||||
|
{
|
||||||
|
$this->sendString('QUIT');
|
||||||
|
//The QUIT command may cause the daemon to exit, which will kill our connection
|
||||||
|
//So ignore errors here
|
||||||
|
try {
|
||||||
|
@fclose($this->pop_conn);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
//Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a response from the POP3 server.
|
||||||
|
*
|
||||||
|
* @param int $size The maximum number of bytes to retrieve
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getResponse($size = 128)
|
||||||
|
{
|
||||||
|
$response = fgets($this->pop_conn, $size);
|
||||||
|
if ($this->do_debug >= 1) {
|
||||||
|
echo 'Server -> Client: ', $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send raw data to the POP3 server.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function sendString($string)
|
||||||
|
{
|
||||||
|
if ($this->pop_conn) {
|
||||||
|
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
|
||||||
|
echo 'Client -> Server: ', $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fwrite($this->pop_conn, $string, strlen($string));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the POP3 server response.
|
||||||
|
* Looks for for +OK or -ERR.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function checkResponse($string)
|
||||||
|
{
|
||||||
|
if (strpos($string, '+OK') !== 0) {
|
||||||
|
$this->setError("Server reported an error: $string");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an error to the internal error store.
|
||||||
|
* Also display debug output if it's enabled.
|
||||||
|
*
|
||||||
|
* @param string $error
|
||||||
|
*/
|
||||||
|
protected function setError($error)
|
||||||
|
{
|
||||||
|
$this->errors[] = $error;
|
||||||
|
if ($this->do_debug >= 1) {
|
||||||
|
echo '<pre>';
|
||||||
|
foreach ($this->errors as $e) {
|
||||||
|
print_r($e);
|
||||||
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of error messages, if any.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POP3 connection error handler.
|
||||||
|
*
|
||||||
|
* @param int $errno
|
||||||
|
* @param string $errstr
|
||||||
|
* @param string $errfile
|
||||||
|
* @param int $errline
|
||||||
|
*/
|
||||||
|
protected function catchWarning($errno, $errstr, $errfile, $errline)
|
||||||
|
{
|
||||||
|
$this->setError(
|
||||||
|
'Connecting to the POP3 server raised a PHP warning:' .
|
||||||
|
"errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
1370
assets/php/phpmailer/SMTP.php
Normal file
1370
assets/php/phpmailer/SMTP.php
Normal file
File diff suppressed because it is too large
Load Diff
55
assets/php/send_email.php
Normal file
55
assets/php/send_email.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
//Import PHPMailer classes into the global namespace
|
||||||
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
use PHPMailer\PHPMailer\SMTP;
|
||||||
|
use PHPMailer\PHPMailer\Exception;
|
||||||
|
|
||||||
|
require_once("./assets/php/phpmailer/Exception.php");
|
||||||
|
require_once("./assets/php/phpmailer/PHPMailer.php");
|
||||||
|
require_once("./assets/php/phpmailer/SMTP.php");
|
||||||
|
|
||||||
|
function send_email($to, $subject, $body, $alt_body, $to_first_name, $to_last_name)
|
||||||
|
{
|
||||||
|
$config_array = json_decode(file_get_contents("config.json", true));
|
||||||
|
|
||||||
|
if (!isset($alt_body)) {
|
||||||
|
$alt_body = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//Create a new PHPMailer instance
|
||||||
|
$mail = new PHPMailer;
|
||||||
|
//Tell PHPMailer to use SMTP
|
||||||
|
$mail->isSMTP();
|
||||||
|
//Enable SMTP debugging
|
||||||
|
// SMTP::DEBUG_OFF = off (for production use)
|
||||||
|
// SMTP::DEBUG_CLIENT = client messages
|
||||||
|
// SMTP::DEBUG_SERVER = client and server messages
|
||||||
|
$mail->SMTPDebug = SMTP::DEBUG_OFF;
|
||||||
|
//Set the hostname of the mail server
|
||||||
|
$mail->Host = 'smtp.gmail.com';
|
||||||
|
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
|
||||||
|
$mail->Port = 587;
|
||||||
|
//Set the encryption mechanism to use - STARTTLS or SMTPS
|
||||||
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||||
|
//Whether to use SMTP authentication
|
||||||
|
$mail->SMTPAuth = true;
|
||||||
|
//Username to use for SMTP authentication - use full email address for gmail
|
||||||
|
$mail->Username = $config_array->{"gmail_username"};
|
||||||
|
//Password to use for SMTP authentication
|
||||||
|
$mail->Password = $config_array->{"gmail_password"};
|
||||||
|
//Set who the message is to be sent from
|
||||||
|
$mail->setFrom($config_array->{"gmail_username"}, 'Food Inventory');
|
||||||
|
//Set an alternative reply-to address
|
||||||
|
$mail->addAddress($to, $to_first_name . " " . $to_last_name);
|
||||||
|
//Set the subject line
|
||||||
|
$mail->Subject = $subject;
|
||||||
|
$mail->Body = $body;
|
||||||
|
//Replace the plain text body with one created manually
|
||||||
|
$mail->AltBody = $alt_body;
|
||||||
|
//send the message, check for errors
|
||||||
|
return ($mail->send());
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
$SESSION_COOKIE_NAME = "connection_id";
|
$SESSION_COOKIE_NAME = "connection_id";
|
||||||
$MAX_COOKIE_LIFE = 86400 * 30; // 30 days max
|
$MAX_COOKIE_LIFE = 86400 * 30; // 30 days max
|
||||||
|
$MAX_RESET_TOKEN_LIFE = 1200; // 20 minutes max
|
||||||
|
$MAX_TOKENS = 3;
|
||||||
$MINIMAL_PASSWORD_LENGTH = 8;
|
$MINIMAL_PASSWORD_LENGTH = 8;
|
||||||
|
|
||||||
$config_array = json_decode(file_get_contents("config.json", true));
|
$config_array = json_decode(file_get_contents("config.json", true));
|
||||||
@ -202,7 +204,6 @@ function add_user($email, $first_name, $last_name, $clear_password)
|
|||||||
return $query->execute();
|
return $query->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function change_user_password($user_id, $new_clear_password)
|
function change_user_password($user_id, $new_clear_password)
|
||||||
{
|
{
|
||||||
global $PDO;
|
global $PDO;
|
||||||
@ -418,3 +419,134 @@ function update_cupboard(
|
|||||||
|
|
||||||
return $query->execute();
|
return $query->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clean_old_reset_tokens()
|
||||||
|
{
|
||||||
|
global $PDO;
|
||||||
|
|
||||||
|
$sql = "DELETE FROM reset_password WHERE token_eol < CURRENT_TIMESTAMP();";
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
return $query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_reset_token_valid($token)
|
||||||
|
{
|
||||||
|
global $PDO;
|
||||||
|
$sql = "SELECT * FROM reset_password WHERE token = :token;";
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
|
||||||
|
$query->bindValue(":token", $token);
|
||||||
|
|
||||||
|
if ($query->execute()) {
|
||||||
|
foreach ($query as $row) {
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete_reset_token($token)
|
||||||
|
{
|
||||||
|
global $PDO;
|
||||||
|
$sql = "DELETE FROM reset_password WHERE token = :token;";
|
||||||
|
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
$query->bindValue(":token", $token);
|
||||||
|
|
||||||
|
return $query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_user_id_from_reset_token($token)
|
||||||
|
{
|
||||||
|
global $PDO;
|
||||||
|
|
||||||
|
$sql = "SELECT accounts.id AS id FROM accounts INNER JOIN reset_password
|
||||||
|
ON accounts.id = reset_password.user_id WHERE token = :token;";
|
||||||
|
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
$query->bindValue(":token", $token);
|
||||||
|
if ($query->execute()) {
|
||||||
|
if ($row = $query->fetch()) {
|
||||||
|
return $row["id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_token_count_from_email($email)
|
||||||
|
{
|
||||||
|
global $PDO;
|
||||||
|
|
||||||
|
$sql = "SELECT token FROM reset_password
|
||||||
|
INNER JOIN accounts ON reset_password.user_id = accounts.id
|
||||||
|
WHERE accounts.email = :email;";
|
||||||
|
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
$query->bindValue(":email", $email);
|
||||||
|
if ($query->execute()) {
|
||||||
|
return $query->rowCount();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate_reset_password_token($email)
|
||||||
|
{
|
||||||
|
global $PDO, $MAX_RESET_TOKEN_LIFE, $MAX_TOKENS;
|
||||||
|
$user_id = get_user_id_from_email($email);
|
||||||
|
if (
|
||||||
|
is_numeric($user_id)
|
||||||
|
&& get_token_count_from_email($email) < $MAX_TOKENS
|
||||||
|
) {
|
||||||
|
$random_token = generate_random_string();
|
||||||
|
$sql = "INSERT INTO reset_password(token, token_eol, user_id)
|
||||||
|
VALUES(:token, :token_eol, :user_id);";
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
$query->bindValue(":token", $random_token);
|
||||||
|
$query->bindValue(
|
||||||
|
":token_eol",
|
||||||
|
date('Y-m-d H:i:s', strtotime("now + $MAX_RESET_TOKEN_LIFE seconds")),
|
||||||
|
PDO::PARAM_STR
|
||||||
|
);
|
||||||
|
$query->bindValue(":user_id", $user_id);
|
||||||
|
if ($query->execute()) {
|
||||||
|
return $random_token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_email_message($link, $first_name)
|
||||||
|
{
|
||||||
|
global $MAX_RESET_TOKEN_LIFE, $MAX_TOKENS;
|
||||||
|
$email = "Hey $first_name,<br>";
|
||||||
|
$email .= "<br>";
|
||||||
|
$email .= "Looks like you asked for a password reset, if so please click the link below (under " . $MAX_RESET_TOKEN_LIFE / 60 . " minutes from now) and reset you password on our website:<br>";
|
||||||
|
$email .= $link . "<br>";
|
||||||
|
$email .= "<br>";
|
||||||
|
$email .= "If it wasn't you who requested this, you can just ignore this message, and nothing will be done.<br>";
|
||||||
|
$email .= "<br>";
|
||||||
|
$email .= "Please remember that each link expires after " . $MAX_RESET_TOKEN_LIFE / 60 . " minutes, so this one will expire exactly at " . date('Y-m-d H:i:s', strtotime("now + $MAX_RESET_TOKEN_LIFE seconds")) . ".<br>";
|
||||||
|
$email .= "You can generate $MAX_TOKENS at maximum. So if you ever want to generate one more after this limit, you'd have to wait for the previous links to be deactivated.<br>";
|
||||||
|
$email .= "<br>";
|
||||||
|
$email .= "Thanks,<br>";
|
||||||
|
$email .= "The Food Inventory system";
|
||||||
|
return ["html" => $email, "alt" => str_replace("<br>", "\n", $email)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_user_info_from_email($email)
|
||||||
|
{
|
||||||
|
global $PDO;
|
||||||
|
|
||||||
|
$sql = "SELECT * FROM accounts WHERE email = :email;";
|
||||||
|
|
||||||
|
$query = $PDO->prepare($sql);
|
||||||
|
$query->bindValue(":email", $email);
|
||||||
|
|
||||||
|
if ($query->execute()) {
|
||||||
|
foreach ($query as $row) {
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
122
forgotten-password.php
Normal file
122
forgotten-password.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
// Include util functions
|
||||||
|
require_once("./assets/php/utils.php");
|
||||||
|
require_once("./assets/php/send_email.php");
|
||||||
|
|
||||||
|
clean_old_reset_tokens();
|
||||||
|
disconnect();
|
||||||
|
|
||||||
|
$password1_err = $password2_err = $mode = $submit_message = $link = "";
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($_GET["token"]) && is_reset_token_valid($_GET["token"])) {
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["password1"]) && isset($_POST["password2"])) {
|
||||||
|
if (empty(trim($_POST["password1"])) || strlen($_POST["password1"]) < $MINIMAL_PASSWORD_LENGTH) {
|
||||||
|
$password1_err = "The password is too short.";
|
||||||
|
} else if ($_POST["password1"] !== $_POST["password2"]) {
|
||||||
|
$password2_err = "Passwords didn't match.";
|
||||||
|
} else {
|
||||||
|
if (change_user_password(get_user_id_from_reset_token($_GET["token"]), $_POST["password1"])) {
|
||||||
|
delete_reset_token($_GET["token"]);
|
||||||
|
header("Location: login.php");
|
||||||
|
} else {
|
||||||
|
$password1_err = $password2_err = "There were an error while changing your password.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
$_SERVER["REQUEST_METHOD"] === "POST" && (!isset($_POST["password1"]) || !isset($_POST["password2"]) || empty(trim($_POST["password1"])) || empty(trim($_POST["password1"])))
|
||||||
|
) {
|
||||||
|
$password1_err = "Please input a new password.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["email"])) {
|
||||||
|
$token = generate_reset_password_token($_POST["email"]);
|
||||||
|
if ($token !== false) {
|
||||||
|
$link = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST']
|
||||||
|
. explode('?', $_SERVER['REQUEST_URI'], 2)[0] . "?token=$token";
|
||||||
|
$row = get_user_info_from_email($_POST["email"]);
|
||||||
|
$email_array = get_email_message($link, $row["first_name"]);
|
||||||
|
if ($row !== false) {
|
||||||
|
send_email(
|
||||||
|
$_POST["email"],
|
||||||
|
"Forgot your password? Let's get you a new one!",
|
||||||
|
$email_array["html"],
|
||||||
|
$email_array["alt"],
|
||||||
|
$row["first_name"],
|
||||||
|
$row["last_name"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$submit_message = "If your e-mail address was correct, you should check your inbox.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<!-- TODO : ADD SEO STUFF -->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<link href="/assets/css/reset.css" rel="stylesheet">
|
||||||
|
<link href="/assets/css/common.css" rel="stylesheet">
|
||||||
|
<link href="/assets/css/login.css" rel="stylesheet">
|
||||||
|
<title>Food inventory - Forgotten password</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="center30left white">
|
||||||
|
<h2 class="montserrat" id="title">Need to reset?</h2>
|
||||||
|
<?php if (isset($_GET["token"]) && is_reset_token_valid($_GET["token"])) {
|
||||||
|
?>
|
||||||
|
<form action="<?php echo htmlspecialchars($_SERVER["REQUEST_URI"]); ?>" method="post">
|
||||||
|
<div class="flex-container flex-evenly">
|
||||||
|
<input type="password" name="password1" class="form-control halo-hover <?php echo (!empty($password1_err)) ? 'has-error' : ''; ?>" placeholder="Password">
|
||||||
|
<input type="password" name="password2" class="form-control halo-hover <?php echo (!empty($password2_err)) ? 'has-error' : ''; ?>" placeholder="Confirm password">
|
||||||
|
</div>
|
||||||
|
<div class="flex-container flex-evenly">
|
||||||
|
<div class="error">
|
||||||
|
<?php
|
||||||
|
if (!empty($password1_err)) echo $password1_err;
|
||||||
|
else echo $password2_err;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group flex-container flex-vertical-center flex-evenly">
|
||||||
|
<input type="submit" class="halo-hover login-button" value="Reset">
|
||||||
|
<a href="/" class="login-button halo-hover other-buttons">Main page</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
if ($submit_message === "") {
|
||||||
|
?>
|
||||||
|
<form action="<?php echo htmlspecialchars($_SERVER["REQUEST_URI"]); ?>" method="post">
|
||||||
|
<div class="flex-container flex-evenly">
|
||||||
|
<input type="email" name="email" class="form-control halo-hover" value="" placeholder="E-mail" required id="lost-email">
|
||||||
|
</div>
|
||||||
|
<div class="flex-container flex-evenly">
|
||||||
|
<div class="error">
|
||||||
|
<?php
|
||||||
|
if (!empty($password1_err)) echo $password1_err;
|
||||||
|
else echo $password2_err;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group flex-container flex-vertical-center flex-evenly">
|
||||||
|
<input type="submit" class="halo-hover login-button" value="Reset">
|
||||||
|
<a href="/" class="login-button halo-hover other-buttons">Main page</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
echo "<p class=\"error\">" . $submit_message . "</p>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -91,7 +91,8 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group flex-container flex-vertical-center flex-evenly">
|
<div class="form-group flex-container flex-vertical-center flex-evenly">
|
||||||
<input type="submit" class="halo-hover login-button" value="Login">
|
<input type="submit" class="halo-hover login-button" value="Login">
|
||||||
<a href="register.php" class="login-button halo-hover other-buttons">You don't have an account? Register!</a>
|
<a href="register.php" class="login-button halo-hover other-buttons">Register</a>
|
||||||
|
<a href="forgotten-password.php" class="login-button halo-hover other-buttons">Forgotten password?</a>
|
||||||
<a href="/" class="login-button halo-hover other-buttons">Main page</a>
|
<a href="/" class="login-button halo-hover other-buttons">Main page</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
Loading…
Reference in New Issue
Block a user