Dump all the stuff from SVN
This commit is contained in:
2
config/.htaccess
Normal file
2
config/.htaccess
Normal file
@ -0,0 +1,2 @@
|
||||
order allow,deny
|
||||
deny from all
|
150
config/config.php
Normal file
150
config/config.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* /config/config.php
|
||||
* @version 1.0
|
||||
* @desc configuration
|
||||
* @author Fándly Gergő Zoltán (gergo@systemtest.tk, systemtest.tk)
|
||||
* @copy 2018 Fándly Gergő Zoltán
|
||||
* License:
|
||||
Systemtest.tk website's.
|
||||
Copyright (C) 2018 Fándly Gergő Zoltán
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
|
||||
const VERSION="0.5";
|
||||
|
||||
/*
|
||||
* Includes
|
||||
*/
|
||||
require_once("lib/loginManager/loginManager.php");
|
||||
require_once("lib/PasswordStorage.php");
|
||||
require_once("lib/functions.php");
|
||||
|
||||
$config=parse_ini_file("config.ini", true);
|
||||
|
||||
/*
|
||||
* Regionals
|
||||
*/
|
||||
date_default_timezone_set($config['general']['timezone']);
|
||||
mb_internal_encoding("UTF-8");
|
||||
|
||||
/*
|
||||
* Language files
|
||||
*/
|
||||
$langstr="";
|
||||
if(isset($_GET['setlang'])){
|
||||
$langstr=$_GET['setlang'];
|
||||
setcookie("language", $langstr, 90*86000);
|
||||
}
|
||||
else if(isset($_COOKIE['language'])){
|
||||
$langstr=$_COOKIE['language'];
|
||||
}
|
||||
else{
|
||||
$langstr=$config['language']['default'];
|
||||
}
|
||||
if(!in_array($langstr, $config['language']['available'])){
|
||||
$langstr=$config['language']['default'];
|
||||
}
|
||||
$langcode="";
|
||||
if($langstr=="en_US"){
|
||||
$langcode="eng";
|
||||
}
|
||||
else if($langstr=="hu_HU"){
|
||||
$langcode="hun";
|
||||
}
|
||||
else if($langstr=="ro_RO"){
|
||||
$langcode="rou";
|
||||
}
|
||||
$lang=parse_ini_file("lang/".$langstr.".ini", false);
|
||||
|
||||
/*
|
||||
* DB setup
|
||||
*/
|
||||
$db=new PDO($config['database']['type'].":host=".$config['database']['host'].";dbname=".$config['database']['name'].";charset=utf8", $config['database']['user'], $config['database']['password']);
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
|
||||
|
||||
/*
|
||||
* UTF8 BOM
|
||||
*/
|
||||
$BOM=chr(239).chr(187).chr(191);
|
||||
|
||||
/*
|
||||
* DEBUG
|
||||
*/
|
||||
if($config['general']['debug']){
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
ini_set("display_errors", true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Login manager
|
||||
*/
|
||||
class handler implements lmHandler{
|
||||
public function handle($state, $target=0){
|
||||
global $db;
|
||||
switch($state){
|
||||
case lmStates::LOGIN_FAILED:
|
||||
functions::setError(1);
|
||||
functions::safeReload();
|
||||
break;
|
||||
case lmStates::LOGIN_OK:
|
||||
$sql=$db->prepare("SELECT id, username, fullname, email, accesslevel, quota, orderer FROM users WHERE id=:id");
|
||||
$sql->execute(array(":id"=>$target));
|
||||
$res=$sql->fetch(PDO::FETCH_ASSOC);
|
||||
$_SESSION['id']=$res['id'];
|
||||
$_SESSION['username']=$res['username'];
|
||||
$_SESSION['fullname']=$res['fullname'];
|
||||
$_SESSION['email']=$res['email'];
|
||||
$_SESSION['accesslevel']=$res['accesslevel'];
|
||||
$_SESSION['quota']=$res['quota'];
|
||||
$_SESSION['orderer']=$res['orderer'];
|
||||
header("Location: /userarea");
|
||||
break;
|
||||
case lmStates::CAPTCHA_FAILED:
|
||||
functions::setError(2);
|
||||
functions::safeReload();
|
||||
break;
|
||||
case lmStates::BANNED:
|
||||
functions::setError(3);
|
||||
functions::safeReload();
|
||||
break;
|
||||
case lmStates::FORGET_DONE:
|
||||
functions::setMessage(1);
|
||||
functions::safeReload();
|
||||
break;
|
||||
case lmStates::LOGOUT_DONE:
|
||||
functions::setMessage(2);
|
||||
functions::safeReload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
class password implements lmPassword{
|
||||
public function verifyPassword($cleartext, $database){
|
||||
if($database==""){
|
||||
return false;
|
||||
}
|
||||
return PasswordStorage::verify_password($cleartext, $database);
|
||||
}
|
||||
}
|
||||
class twoFactor implements lmTwoFactor{
|
||||
public function secondFactor($uid){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$lm=new loginManager(new lmConfig($db, $config['login']['session_lifetime'], $config['login']['captcha_enable'], $config['login']['captcha_after'], $config['login']['captcha_sitekey'], $config['login']['captcha_secretkey'], $config['login']['ban_enable'], $config['login']['ban_after'], $config['login']['ban_time'], $config['login']['look'], $config['login']['remember_enable'], $config['login']['remember_time'], lmStates::AUTH_UNAME), new handler(), new password(), new twoFactor());
|
||||
$lm->init();
|
213
config/database setup.sql
Normal file
213
config/database setup.sql
Normal file
@ -0,0 +1,213 @@
|
||||
/**
|
||||
* /config/database setup.php
|
||||
* @version 1.0
|
||||
* @desc Database setup
|
||||
* @author Fándly Gergő Zoltán (gergo@systemtest.tk, systemtest.tk)
|
||||
* @copy 2018 Fándly Gergő Zoltán
|
||||
* License:
|
||||
Systemtest.tk website's.
|
||||
Copyright (C) 2018 Fándly Gergő Zoltán
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
CREATE TABLE `users`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`username` varchar(65) NOT NULL default '', /* optional */
|
||||
`fullname` varchar(65) NOT NULL default '',
|
||||
`email` varchar(65) NOT NULL default '',
|
||||
`accesslevel` tinyint(1) UNSIGNED NOT NULL default 0, /* 0-regular user; 1-blogger; 2-order handler/helpdesk; 3-admin */
|
||||
`quota` int(4) NOT NULL default 100, /* quota in MBs; -1 for unlimited */
|
||||
`orderer` varchar(35) default null,
|
||||
`password` varchar(255) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`orderer`) REFERENCES orderers(`reference`) ON DELETE SET NULL
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `login_history`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`user` int(4) UNSIGNED NOT NULL default 1, /* id of nouser */
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`ip` varchar(45) NOT NULL default '0.0.0.0',
|
||||
`auth_token` varchar(65) NOT NULL default '',
|
||||
`user_agent` varchar(500) NOT NULL default '',
|
||||
`success` tinyint(1) NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`user`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `login_remember`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`user` int(4) UNSIGNED NOT NULL default 0,
|
||||
`remember_token` varchar(65) NOT NULL default '',
|
||||
`until` timestamp NOT NULL default current_timestamp,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`user`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `login_bans`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`ip` varchar(45) NOT NULL default '0.0.0.0',
|
||||
`until` timestamp NOT NULL default current_timestamp,
|
||||
PRIMARY KEY (`id`)
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `projects` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`name` varchar(65) NOT NULL default '',
|
||||
`description` text NOT NULL default '',
|
||||
`owner` int(4) UNSIGNED NOT NULL default 0,
|
||||
`path` varchar(125) NOT NULL default '',
|
||||
`repo` varchar(125) NOT NULL default '',
|
||||
`status` varchar(65) NOT NULL default '',
|
||||
`image` text NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`owner`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `files` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`token` varchar(35) NOT NULL default '', /* MD5 hash computed from {name}<<<>>>{random 16 char string} */
|
||||
`owner` int(4) UNSIGNED NOT NULL default 0,
|
||||
`name` varchar(65) NOT NULL default 0,
|
||||
`extension` varchar(20) NOT NULL default '.*',
|
||||
`size` int(4) UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`owner`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `news` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`owner` int(4) UNSIGNED NOT NULL default 0,
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`subject_eng` varchar(65) NOT NULL default '',
|
||||
`subject_hun` varchar(65) NOT NULL default '',
|
||||
`subject_rou` varchar(65) NOT NULL default '',
|
||||
`content_eng` text NOT NULL default '',
|
||||
`content_hun` text NOT NULL default '',
|
||||
`content_rou` text NOT NULL default '',
|
||||
`published` tinyint(1) UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`owner`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `blog` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`title` varchar(65) NOT NULL default '',
|
||||
`owner` int(4) UNSIGNED NOT NULL default 0,
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`content` text NOT NULL default '',
|
||||
`published` tinyint(1) UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`owner`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `blog_tags` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`blogentry` int(4) UNSIGNED NOT NULL default 0,
|
||||
`tag` varchar(65) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`blogentry`) REFERENCES blog(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `products` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`name_eng` varchar(65) NOT NULL default '',
|
||||
`name_hun` varchar(65) NOT NULL default '',
|
||||
`name_rou` varchar(65) NOT NULL default '',
|
||||
`description_eng` text NOT NULL default '',
|
||||
`description_hun` text NOT NULL default '',
|
||||
`description_rou` text NOT NULL default '',
|
||||
`price` int(4) NOT NULL default 0, /* if -2: to be announced, -1: contact us */
|
||||
PRIMARY KEY (`id`)
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `product_tags` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`product` int(4) UNSIGNED NOT NULL default 0,
|
||||
`tag` varchar(65) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`product`) REFERENCES products(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `product_images` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`product` int(4) UNSIGNED NOT NULL default 0,
|
||||
`image` int(4) UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`product`) REFERENCES products(`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`image`) REFERENCES files(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `product_reviews` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`orderid` int(4) UNSIGNED NOT NULL default 0,
|
||||
`writer` varchar(65) NOT NULL default 'Anonymous',
|
||||
`rating` tinyint(1) UNSIGNED NOT NULL default 5, /* from 1 to 5 */
|
||||
`comment` varchar(2000) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`orderid`) REFERENCES orders(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `orderers` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`reference` varchar(35) NOT NULL default '', /* md5 hash computed from {current timestamp}<<<>>>{random 16 char string} */
|
||||
`name` text NOT NULL default '', /* encrypted */
|
||||
`address` text NOT NULL default '',
|
||||
`email` text NOT NULL default '',
|
||||
`phone` text NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY (`reference`)
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `orders` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`reference` varchar(35) NOT NULL default '', /* md5 hash reference computed from {current timestamp}<<<>>>{random 16 char string} */
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`product` int(4) UNSIGNED default 0,
|
||||
`quantity` int(4) UNSIGNED NOT NULL default 1,
|
||||
`orderer` varchar(35) default '',
|
||||
`comments` text NOT NULL default '',
|
||||
`status` tinyint(1) UNSIGNED NOT NULL default 0, /* 0:order placed; 1:preprocessing, produceing; 2:waiting payment; 3:payed; 4:packing; 5:shipped; 6:arrieved; 10:order cancelled */
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`product`) REFERENCES products(`id`) ON DELETE SET NULL,
|
||||
FOREIGN KEY (`orderer`) REFERENCES orderers(`reference`) ON DELETE SET NULL
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `messages` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`subject` varchar(65) NOT NULL default '',
|
||||
`message` varchar(1500) NOT NULL default '',
|
||||
`blogentry` int(4) UNSIGNED default NULL,
|
||||
`product` int(4) UNSIGNED default NULL,
|
||||
`orderid` int(4) UNSIGNED default NULL,
|
||||
`replyemail` varchar(65) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`blogentry`) REFERENCES blog(`id`) ON DELETE SET NULL,
|
||||
FOREIGN KEY (`product`) REFERENCES products(`id`) ON DELETE SET NULL,
|
||||
FOREIGN KEY (`orderid`) REFERENCES orders(`id`) ON DELETE SET NULL
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `data_requests` (
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`user` int(4) UNSIGNED NOT NULL default 1,
|
||||
`pgp` varchar(10000) NOT NULL default '',
|
||||
`finished` tinyint(1) NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`user`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
INSERT INTO users (`id`, `username`) VALUES (1, 'nouser');
|
144
config/lang/en_US.ini
Normal file
144
config/lang/en_US.ini
Normal file
@ -0,0 +1,144 @@
|
||||
sitetitle="Systemtest"
|
||||
cookie_message="This site uses cookies to ensure you have the best experience on our website."
|
||||
cookie_dismiss="Got it!"
|
||||
cookie_link="Learn more"
|
||||
index="Home"
|
||||
projects="Projects"
|
||||
repos="Repositories"
|
||||
blog="Blog"
|
||||
about="About us"
|
||||
userarea="User area"
|
||||
products="Products"
|
||||
contact="Contact"
|
||||
index_content="Hi there! This is a site where I test my projects, ocasionally post some stuff and write articles which I hope will offer help to some people (these are mostly in Hungarian). I also have an SVN repository, a small file share server (100MB lifetime storage for free) and a products tab where I offer services (building websites, configuring networks, servers, etc) but also some pre-built projects (for example an automated, programmable aquarium fertilizer).<br>If you have any question or you just have something to say, feel free to write me!<br>Have a good day!"
|
||||
news="News"
|
||||
loadmore="Load more!"
|
||||
projects_content="Here you can find the projects I made."
|
||||
view="View"
|
||||
source="Source"
|
||||
keywords="Keywords"
|
||||
readmore="Read more"
|
||||
login="Log in"
|
||||
username="Username"
|
||||
password="Password"
|
||||
ok="Ok!"
|
||||
welcome_back_1="Welcome back, "
|
||||
welcome_back_2="!"
|
||||
forget_user="Somebody else? Or just want to forget?"
|
||||
remember="Remember me"
|
||||
fileshare="File share"
|
||||
profile="Profile"
|
||||
orders="Orders"
|
||||
messages="Messages"
|
||||
adminarea="Administrator area"
|
||||
logout="Log out"
|
||||
name="Name"
|
||||
files="Your files"
|
||||
extension="Extension"
|
||||
operations="Operations"
|
||||
reference="Reference"
|
||||
copytoclip="Copy to clipboard"
|
||||
delete="Delete"
|
||||
quota="Quota"
|
||||
size="Size"
|
||||
upload="Upload"
|
||||
clear="Clear"
|
||||
sure="Are you sure?"
|
||||
owner="Owner"
|
||||
date="Date"
|
||||
published="Published"
|
||||
tags="Tags"
|
||||
tyes="Yes"
|
||||
tno="No"
|
||||
edit="Edit"
|
||||
editor="Editor"
|
||||
title="Title"
|
||||
save="Save"
|
||||
discard="Discard"
|
||||
autosave="Auto save"
|
||||
last_saved="Last saved"
|
||||
new="New"
|
||||
subject="Subject"
|
||||
eng="English"
|
||||
hun="Hungarian"
|
||||
rou="Romanian"
|
||||
id="ID"
|
||||
accesslevel="Access level"
|
||||
email="Email address"
|
||||
encrypted="Encrypted"
|
||||
ch_passwd="Change password"
|
||||
ch_accesslevel="Change access level"
|
||||
new_user="New user"
|
||||
password_confirm="Confirm password"
|
||||
cancel="Cancel"
|
||||
enter_password="Please enter the new password!"
|
||||
enter_accesslevel="Pleade enter the new accesslevel"
|
||||
fullname="Full name"
|
||||
emailspoiler="This address is only used to recover your account. It is not needed to set it, you can leave it empty."
|
||||
status="Status"
|
||||
set="Already set"
|
||||
not_set="Not set"
|
||||
profile_shipping_address_spoiler="If your shipping address is already set, we can't show it to you, because they are asymmetrically encrypted and the private key is stored off-site for maximum safety. If you want to update it, please set it below, all the previous entries will be deleted."
|
||||
shipping_address_spoiler="The shipping addresses are stored safely encrypted with a 4096 bit asymetric RSA key. It can only be viewed when the coresponding private key is supplied. This key is stored off-site divided into multiple parts, owned by the administrators of this page. The parts are only paired when shipping your order. After your command is finalized all the shipping data will be removed from our database if you specifically doesn't save it for further use (by registering an account). The encryption keypair is changed periodically and the encryption/decryption is done on the client side, so maximum confidence can be assured."
|
||||
shipping_name="Shipping and facturing name"
|
||||
shipping_country="Country"
|
||||
shipping_region="State/Province/Region"
|
||||
shipping_city="City"
|
||||
shipping_address_line1="Address line 1"
|
||||
shipping_address_line2="Address line 2"
|
||||
shipping_zip="Zip/Postal code"
|
||||
shipping_email="Contact email"
|
||||
shipping_phone="Phone number (with prefix)"
|
||||
shipping_phone_example="ex: +40770000000"
|
||||
shipping_address="Shipping address"
|
||||
encrypting="Encryption"
|
||||
confirm_delete_shipping="Are you sure you wan't to remove your shipping address? This will affect all your current orders which aren't in the shipped state yet."
|
||||
delete_profile="Delete profile"
|
||||
sure_2="Absolutely sure?"
|
||||
sure_3="Totally?"
|
||||
delete_profile_spoiler="If you delete your profile it will be unrecoverable. All the data which is related with your profile (this includes: username, your full name, email address, shipping address, all your files and your login history), but the orders you placed, your reviews and the messages you left won't be deleted, because they arn't linked to your account. But don't panic, they are completely anonym. The invoices however will be kept for legal reasons."
|
||||
get_all_profile_data="Get all my data!"
|
||||
get_all_profile_data_spoiler="We offer you to download all the data which is stored in our database and can be linked to your profile (username, full name, email address, shipping address, login history and you previous data requests). All the data will be sent to you in email, so it is required to set a contact email address (you can delete it afterwards). If you want to receive your data encrypted, you can set a public PGP key, but it's not required. These requests are processed manually, so please be patient. It may take up to 2 weeks (but it's usually done in 3-5 days)."
|
||||
pgp_public="Public PGP key"
|
||||
date="Date"
|
||||
finished="Finished"
|
||||
userlist="User list"
|
||||
requestlist="Request list"
|
||||
ch_quota="Change quota"
|
||||
enter_quota="Pleade enter the new quota"
|
||||
unlimited="Unlimited"
|
||||
finish="Finalize!"
|
||||
send_message="Send message"
|
||||
message="Message"
|
||||
|
||||
;Errors
|
||||
error[1]="Wrong username or password!"
|
||||
error[2]="Please fill in the reCaptcha!"
|
||||
error[3]="Due to many failed login attempts, your IP address have been blocked for 10 minutes!"
|
||||
error[4]="Your quota has been reached!"
|
||||
error[5]="Your file is bigger than 500MB. Unfortunately we can't handle it."
|
||||
error[6]="Something went wrong. Please try again later!"
|
||||
error[7]="Nothing found with this ID."
|
||||
error[8]="Passwords doesn't match."
|
||||
error[9]="Username already taken."
|
||||
error[10]="Something went wrong while we were deleting your profile. This probably lead to data corruption. Please contact us!"
|
||||
error[11]="You already have a pending request. Please be patient!"
|
||||
error[12]="The supplied PGP public key is not valid!"
|
||||
error[404]="Page not found."
|
||||
error[500]="You have no permission to access that page!"
|
||||
|
||||
;Messages
|
||||
message[1]="Your login credintials have been removed from this computer successfully."
|
||||
message[2]="You have been logged out successfully."
|
||||
message[3]="File deleted successfully."
|
||||
message[4]="Edit submitted successfully."
|
||||
message[5]="Entry deleted successfully."
|
||||
message[6]="User successfully created."
|
||||
message[7]="Profile successfully edited."
|
||||
message[8]="Password successfully updated."
|
||||
message[9]="Shipping information successfully updated."
|
||||
message[10]="Shipping information successfully added."
|
||||
message[11]="Shipping information successfully deleted."
|
||||
message[12]="Your profile has been deleted successfully. You won't be able to log in anymore. This process is irreversible."
|
||||
message[13]="Request submitted successfully. Please be patient!"
|
||||
message[14]="That's done, bro!"
|
333
config/lib/PasswordStorage.php
Normal file
333
config/lib/PasswordStorage.php
Normal file
@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
class InvalidHashException extends Exception {}
|
||||
class CannotPerformOperationException extends Exception {}
|
||||
|
||||
class PasswordStorage
|
||||
{
|
||||
// These constants may be changed without breaking existing hashes.
|
||||
const PBKDF2_HASH_ALGORITHM = "sha1";
|
||||
const PBKDF2_ITERATIONS = 64000;
|
||||
const PBKDF2_SALT_BYTES = 24;
|
||||
const PBKDF2_OUTPUT_BYTES = 18;
|
||||
|
||||
// These constants define the encoding and may not be changed.
|
||||
const HASH_SECTIONS = 5;
|
||||
const HASH_ALGORITHM_INDEX = 0;
|
||||
const HASH_ITERATION_INDEX = 1;
|
||||
const HASH_SIZE_INDEX = 2;
|
||||
const HASH_SALT_INDEX = 3;
|
||||
const HASH_PBKDF2_INDEX = 4;
|
||||
|
||||
/**
|
||||
* Hash a password with PBKDF2
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function create_hash($password)
|
||||
{
|
||||
// format: algorithm:iterations:outputSize:salt:pbkdf2output
|
||||
if (!\is_string($password)) {
|
||||
throw new InvalidArgumentException(
|
||||
"create_hash(): Expected a string"
|
||||
);
|
||||
}
|
||||
if (\function_exists('random_bytes')) {
|
||||
try {
|
||||
$salt_raw = \random_bytes(self::PBKDF2_SALT_BYTES);
|
||||
} catch (Error $e) {
|
||||
$salt_raw = false;
|
||||
} catch (Exception $e) {
|
||||
$salt_raw = false;
|
||||
} catch (TypeError $e) {
|
||||
$salt_raw = false;
|
||||
}
|
||||
} else {
|
||||
$salt_raw = \mcrypt_create_iv(self::PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM);
|
||||
}
|
||||
if ($salt_raw === false) {
|
||||
throw new CannotPerformOperationException(
|
||||
"Random number generator failed. Not safe to proceed."
|
||||
);
|
||||
}
|
||||
|
||||
$PBKDF2_Output = self::pbkdf2(
|
||||
self::PBKDF2_HASH_ALGORITHM,
|
||||
$password,
|
||||
$salt_raw,
|
||||
self::PBKDF2_ITERATIONS,
|
||||
self::PBKDF2_OUTPUT_BYTES,
|
||||
true
|
||||
);
|
||||
|
||||
return self::PBKDF2_HASH_ALGORITHM .
|
||||
":" .
|
||||
self::PBKDF2_ITERATIONS .
|
||||
":" .
|
||||
self::PBKDF2_OUTPUT_BYTES .
|
||||
":" .
|
||||
\base64_encode($salt_raw) .
|
||||
":" .
|
||||
\base64_encode($PBKDF2_Output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a password matches the stored hash
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $hash
|
||||
* @return bool
|
||||
*/
|
||||
public static function verify_password($password, $hash)
|
||||
{
|
||||
if (!\is_string($password) || !\is_string($hash)) {
|
||||
throw new InvalidArgumentException(
|
||||
"verify_password(): Expected two strings"
|
||||
);
|
||||
}
|
||||
$params = \explode(":", $hash);
|
||||
if (\count($params) !== self::HASH_SECTIONS) {
|
||||
throw new InvalidHashException(
|
||||
"Fields are missing from the password hash."
|
||||
);
|
||||
}
|
||||
|
||||
$pbkdf2 = \base64_decode($params[self::HASH_PBKDF2_INDEX], true);
|
||||
if ($pbkdf2 === false) {
|
||||
throw new InvalidHashException(
|
||||
"Base64 decoding of pbkdf2 output failed."
|
||||
);
|
||||
}
|
||||
|
||||
$salt_raw = \base64_decode($params[self::HASH_SALT_INDEX], true);
|
||||
if ($salt_raw === false) {
|
||||
throw new InvalidHashException(
|
||||
"Base64 decoding of salt failed."
|
||||
);
|
||||
}
|
||||
|
||||
$storedOutputSize = (int) $params[self::HASH_SIZE_INDEX];
|
||||
if (self::ourStrlen($pbkdf2) !== $storedOutputSize) {
|
||||
throw new InvalidHashException(
|
||||
"PBKDF2 output length doesn't match stored output length."
|
||||
);
|
||||
}
|
||||
|
||||
$iterations = (int) $params[self::HASH_ITERATION_INDEX];
|
||||
if ($iterations < 1) {
|
||||
throw new InvalidHashException(
|
||||
"Invalid number of iterations. Must be >= 1."
|
||||
);
|
||||
}
|
||||
|
||||
return self::slow_equals(
|
||||
$pbkdf2,
|
||||
self::pbkdf2(
|
||||
$params[self::HASH_ALGORITHM_INDEX],
|
||||
$password,
|
||||
$salt_raw,
|
||||
$iterations,
|
||||
self::ourStrlen($pbkdf2),
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two strings $a and $b in length-constant time.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return bool
|
||||
*/
|
||||
public static function slow_equals($a, $b)
|
||||
{
|
||||
if (!\is_string($a) || !\is_string($b)) {
|
||||
throw new InvalidArgumentException(
|
||||
"slow_equals(): expected two strings"
|
||||
);
|
||||
}
|
||||
if (\function_exists('hash_equals')) {
|
||||
return \hash_equals($a, $b);
|
||||
}
|
||||
|
||||
// PHP < 5.6 polyfill:
|
||||
$diff = self::ourStrlen($a) ^ self::ourStrlen($b);
|
||||
for($i = 0; $i < self::ourStrlen($a) && $i < self::ourStrlen($b); $i++) {
|
||||
$diff |= \ord($a[$i]) ^ \ord($b[$i]);
|
||||
}
|
||||
return $diff === 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
|
||||
* $algorithm - The hash algorithm to use. Recommended: SHA256
|
||||
* $password - The password.
|
||||
* $salt - A salt that is unique to the password.
|
||||
* $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
|
||||
* $key_length - The length of the derived key in bytes.
|
||||
* $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
|
||||
* Returns: A $key_length-byte key derived from the password and salt.
|
||||
*
|
||||
* Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
|
||||
*
|
||||
* This implementation of PBKDF2 was originally created by https://defuse.ca
|
||||
* With improvements by http://www.variations-of-shadow.com
|
||||
*/
|
||||
public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
|
||||
{
|
||||
// Type checks:
|
||||
if (!\is_string($algorithm)) {
|
||||
throw new InvalidArgumentException(
|
||||
"pbkdf2(): algorithm must be a string"
|
||||
);
|
||||
}
|
||||
if (!\is_string($password)) {
|
||||
throw new InvalidArgumentException(
|
||||
"pbkdf2(): password must be a string"
|
||||
);
|
||||
}
|
||||
if (!\is_string($salt)) {
|
||||
throw new InvalidArgumentException(
|
||||
"pbkdf2(): salt must be a string"
|
||||
);
|
||||
}
|
||||
// Coerce strings to integers with no information loss or overflow
|
||||
$count += 0;
|
||||
$key_length += 0;
|
||||
|
||||
$algorithm = \strtolower($algorithm);
|
||||
if (!\in_array($algorithm, \hash_algos(), true)) {
|
||||
throw new CannotPerformOperationException(
|
||||
"Invalid or unsupported hash algorithm."
|
||||
);
|
||||
}
|
||||
|
||||
// Whitelist, or we could end up with people using CRC32.
|
||||
$ok_algorithms = array(
|
||||
"sha1", "sha224", "sha256", "sha384", "sha512",
|
||||
"ripemd160", "ripemd256", "ripemd320", "whirlpool"
|
||||
);
|
||||
if (!\in_array($algorithm, $ok_algorithms, true)) {
|
||||
throw new CannotPerformOperationException(
|
||||
"Algorithm is not a secure cryptographic hash function."
|
||||
);
|
||||
}
|
||||
|
||||
if ($count <= 0 || $key_length <= 0) {
|
||||
throw new CannotPerformOperationException(
|
||||
"Invalid PBKDF2 parameters."
|
||||
);
|
||||
}
|
||||
|
||||
if (\function_exists("hash_pbkdf2")) {
|
||||
// The output length is in NIBBLES (4-bits) if $raw_output is false!
|
||||
if (!$raw_output) {
|
||||
$key_length = $key_length * 2;
|
||||
}
|
||||
return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
|
||||
}
|
||||
|
||||
$hash_length = self::ourStrlen(\hash($algorithm, "", true));
|
||||
$block_count = \ceil($key_length / $hash_length);
|
||||
|
||||
$output = "";
|
||||
for($i = 1; $i <= $block_count; $i++) {
|
||||
// $i encoded as 4 bytes, big endian.
|
||||
$last = $salt . \pack("N", $i);
|
||||
// first iteration
|
||||
$last = $xorsum = \hash_hmac($algorithm, $last, $password, true);
|
||||
// perform the other $count - 1 iterations
|
||||
for ($j = 1; $j < $count; $j++) {
|
||||
$xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
|
||||
}
|
||||
$output .= $xorsum;
|
||||
}
|
||||
|
||||
if($raw_output) {
|
||||
return self::ourSubstr($output, 0, $key_length);
|
||||
} else {
|
||||
return \bin2hex(self::ourSubstr($output, 0, $key_length));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need these strlen() and substr() functions because when
|
||||
* 'mbstring.func_overload' is set in php.ini, the standard strlen() and
|
||||
* substr() are replaced by mb_strlen() and mb_substr().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculate the length of a string
|
||||
*
|
||||
* @param string $str
|
||||
* @return int
|
||||
*/
|
||||
private static function ourStrlen($str)
|
||||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \function_exists('mb_strlen');
|
||||
}
|
||||
|
||||
if (!\is_string($str)) {
|
||||
throw new InvalidArgumentException(
|
||||
"ourStrlen() expects a string"
|
||||
);
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
$length = \mb_strlen($str, '8bit');
|
||||
if ($length === false) {
|
||||
throw new CannotPerformOperationException();
|
||||
}
|
||||
return $length;
|
||||
} else {
|
||||
return \strlen($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Substring
|
||||
*
|
||||
* @param string $str
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
private static function ourSubstr($str, $start, $length = null)
|
||||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \function_exists('mb_substr');
|
||||
}
|
||||
// Type validation:
|
||||
if (!\is_string($str)) {
|
||||
throw new InvalidArgumentException(
|
||||
"ourSubstr() expects a string"
|
||||
);
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
// mb_substr($str, 0, NULL, '8bit') returns an empty string on PHP
|
||||
// 5.3, so we have to find the length ourselves.
|
||||
if (!isset($length)) {
|
||||
if ($start >= 0) {
|
||||
$length = self::ourStrlen($str) - $start;
|
||||
} else {
|
||||
$length = -$start;
|
||||
}
|
||||
}
|
||||
|
||||
return \mb_substr($str, $start, $length, '8bit');
|
||||
}
|
||||
|
||||
// Unlike mb_substr(), substr() doesn't accept NULL for length
|
||||
if (isset($length)) {
|
||||
return \substr($str, $start, $length);
|
||||
} else {
|
||||
return \substr($str, $start);
|
||||
}
|
||||
}
|
||||
}
|
274
config/lib/functions.php
Normal file
274
config/lib/functions.php
Normal file
@ -0,0 +1,274 @@
|
||||
<?php
|
||||
/**
|
||||
* functions.php
|
||||
* @version 2.4
|
||||
* @desc General issued php function library for me
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
class functions{
|
||||
const STR_SAME=0;
|
||||
const STR_LOWERCASE=1;
|
||||
const STR_RACCENT=2;
|
||||
const STR_RACCLOW=3;
|
||||
const RAND_SMALL=0;
|
||||
const RAND_LARGE=1;
|
||||
const RAND_SPEC=2;
|
||||
const COOKIE_LIFETIME=3;
|
||||
|
||||
public static function setError($code){
|
||||
global $errcode;
|
||||
if(isset($errcode)){
|
||||
array_push($errcode, $code);
|
||||
}
|
||||
else{
|
||||
$errcode=array($code);
|
||||
}
|
||||
setcookie("errcode", serialize($errcode), time()+functions::COOKIE_LIFETIME);
|
||||
}
|
||||
|
||||
public static function isError(){
|
||||
global $errcode;
|
||||
if(isset($errcode) || isset($_COOKIE['errcode'])){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getErrorArray(){
|
||||
global $errcode;
|
||||
if(functions::isError()){
|
||||
if(isset($errcode)){
|
||||
return $errcode;
|
||||
}
|
||||
if(isset($_COOKIE['errcode'])){
|
||||
return unserialize($_COOKIE['errcode']);
|
||||
}
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static function setMessage($code){
|
||||
global $msgcode;
|
||||
if(isset($msgcode)){
|
||||
array_push($msgcode, $code);
|
||||
}
|
||||
else{
|
||||
$msgcode=array($code);
|
||||
}
|
||||
setcookie("msgcode", serialize($msgcode), time()+functions::COOKIE_LIFETIME);
|
||||
}
|
||||
|
||||
public static function isMessage(){
|
||||
global $msgcode;
|
||||
if(isset($msgcode) || isset($_COOKIE['msgcode'])){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getMessageArray(){
|
||||
global $msgcode;
|
||||
if(functions::isMessage()){
|
||||
if(isset($msgcode)){
|
||||
return $msgcode;
|
||||
}
|
||||
if(isset($_COOKIE['msgcode'])){
|
||||
return unserialize($_COOKIE['msgcode']);
|
||||
}
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static function clearError(){
|
||||
global $errcode;
|
||||
if(isset($errcode)){
|
||||
unset($errcode);
|
||||
}
|
||||
setcookie("errcode", null, -1);
|
||||
}
|
||||
|
||||
public static function clearMessage(){
|
||||
global $msgcode;
|
||||
if(isset($msgcode)){
|
||||
unset($msgcode);
|
||||
}
|
||||
setcookie("msgcode", null, -1);
|
||||
}
|
||||
|
||||
public static function safeReload(){
|
||||
header("Location: ".explode("?", $_SERVER['REQUEST_URI'])[0]);
|
||||
}
|
||||
|
||||
public static function randomString($length, $char=functions::RAND_SMALL){
|
||||
if($char==0){
|
||||
$charset="0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
}
|
||||
else if($char==1){
|
||||
$charset="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
}
|
||||
else if($char==2){
|
||||
$charset="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_-=+\?/.>,<";
|
||||
}
|
||||
$charsetlength=strlen($charset);
|
||||
$string="";
|
||||
for($i=0; $i<$length; $i++){
|
||||
$string=$string . $charset[rand(0, $charsetlength-1)];
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
public static function get_string_between($string, $start, $end){
|
||||
$string=' ' . $string;
|
||||
$ini=strpos($string, $start);
|
||||
if($ini==0) return '';
|
||||
$ini+=strlen($start);
|
||||
$len=strpos($string, $end, $ini) - $ini;
|
||||
return substr($string, $ini, $len);
|
||||
}
|
||||
|
||||
public static function process_string($str, $dep){
|
||||
global $functions_accent_convert;
|
||||
switch($dep){
|
||||
case 0:
|
||||
{
|
||||
return $str;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
return strtolower($str);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return strtr($str, $functions_accent_convert);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
return strtolower(strtr($str, $functions_accent_convert));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function validate_captcha($secretkey, $response){
|
||||
$verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$response);
|
||||
$data=json_decode($verify);
|
||||
if($data->success){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$functions_accent_convert=array(
|
||||
// Decompositions for Latin-1 Supplement
|
||||
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
|
||||
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
|
||||
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
|
||||
chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
|
||||
chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
|
||||
chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
|
||||
chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
|
||||
chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
|
||||
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
|
||||
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
|
||||
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
|
||||
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
|
||||
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
|
||||
chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
|
||||
chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
|
||||
chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
|
||||
chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
|
||||
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
|
||||
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
|
||||
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
|
||||
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
|
||||
chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
|
||||
chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
|
||||
chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
|
||||
chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
|
||||
chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
|
||||
chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
|
||||
chr(195).chr(191) => 'y',
|
||||
// Decompositions for Latin Extended-A
|
||||
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
|
||||
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
|
||||
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
|
||||
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
|
||||
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
|
||||
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
|
||||
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
|
||||
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
|
||||
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
|
||||
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
|
||||
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
|
||||
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
|
||||
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
|
||||
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
|
||||
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
|
||||
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
|
||||
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
|
||||
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
|
||||
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
|
||||
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
|
||||
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
|
||||
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
|
||||
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
|
||||
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
|
||||
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
|
||||
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
|
||||
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
|
||||
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
|
||||
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
|
||||
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
|
||||
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
|
||||
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
|
||||
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
|
||||
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
|
||||
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
|
||||
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
|
||||
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
|
||||
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
|
||||
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
|
||||
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
|
||||
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
|
||||
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
|
||||
chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
|
||||
chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
|
||||
chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
|
||||
chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
|
||||
chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
|
||||
chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
|
||||
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
|
||||
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
|
||||
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
|
||||
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
|
||||
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
|
||||
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
|
||||
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
|
||||
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
|
||||
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
|
||||
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
|
||||
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
|
||||
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
|
||||
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
|
||||
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
|
||||
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
|
||||
chr(197).chr(190) => 'z', chr(197).chr(191) => 's');
|
||||
|
||||
?>
|
82
config/lib/loginManager/lmConfig.php
Normal file
82
config/lib/loginManager/lmConfig.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/lmConfig.php
|
||||
* @version 1.3
|
||||
* @desc config class
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
class lmConfig{
|
||||
public function __construct($_pdo, $_session_lifetime, $_captcha_enable, $_captcha_after, $_captcha_sitekey, $_captcha_secretkey, $_ban_enable, $_ban_after, $_ban_time, $_look, $_remember_enable, $_remember_time, $_auth_type){
|
||||
$this->pdo=$_pdo;
|
||||
$this->session_lifetime=$_session_lifetime;
|
||||
$this->captcha_enable=$_captcha_enable;
|
||||
$this->captcha_after=$_captcha_after;
|
||||
$this->captcha_sitekey=$_captcha_sitekey;
|
||||
$this->captcha_secretkey=$_captcha_secretkey;
|
||||
$this->ban_enable=$_ban_enable;
|
||||
$this->ban_after=$_ban_after;
|
||||
$this->ban_time=$_ban_time;
|
||||
$this->look=$_look;
|
||||
$this->remember_enable=$_remember_enable;
|
||||
$this->remember_time=$_remember_time;
|
||||
$this->auth_type=$_auth_type;
|
||||
}
|
||||
|
||||
private $pdo;
|
||||
private $session_lifetime;
|
||||
private $captcha_enable;
|
||||
private $captcha_after;
|
||||
private $captcha_sitekey;
|
||||
private $captcha_secretkey;
|
||||
private $ban_enable;
|
||||
private $ban_after;
|
||||
private $ban_time;
|
||||
private $look;
|
||||
private $remember_enable; //NOT SAFE AT ALL!!!
|
||||
private $remember_time;
|
||||
private $auth_type;
|
||||
|
||||
public function getPDO(){
|
||||
return $this->pdo;
|
||||
}
|
||||
public function getSessionLifetime(){
|
||||
return $this->session_lifetime;
|
||||
}
|
||||
public function isCaptchaEnabled(){
|
||||
return $this->captcha_enable;
|
||||
}
|
||||
public function getCaptchaAfter(){
|
||||
return $this->captcha_after;
|
||||
}
|
||||
public function getCaptchaSitekey(){
|
||||
return $this->captcha_sitekey;
|
||||
}
|
||||
public function getCaptchaSecretkey(){
|
||||
return $this->captcha_secretkey;
|
||||
}
|
||||
public function isBanEnabled(){
|
||||
return $this->ban_enable;
|
||||
}
|
||||
public function getBanAfter(){
|
||||
return $this->ban_after;
|
||||
}
|
||||
public function getBanTime(){
|
||||
return $this->ban_time;
|
||||
}
|
||||
public function getLook(){
|
||||
return $this->look;
|
||||
}
|
||||
public function isRememberEnabled(){
|
||||
return $this->remember_enable;
|
||||
}
|
||||
public function getRememberTime(){
|
||||
return $this->remember_time;
|
||||
}
|
||||
public function getAuthType(){
|
||||
return $this->auth_type;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
14
config/lib/loginManager/lmHandler.php
Normal file
14
config/lib/loginManager/lmHandler.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/lmHandler.php
|
||||
* @version 1.1
|
||||
* @desc Event handler for login manager
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
interface lmHandler{
|
||||
public function handle($state, $target=0);
|
||||
}
|
||||
|
||||
?>
|
14
config/lib/loginManager/lmPassword.php
Normal file
14
config/lib/loginManager/lmPassword.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/lmPassword.php
|
||||
* @version 1.0
|
||||
* @desc interface for function verifying password
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
interface lmPassword{
|
||||
public function verifyPassword($cleartext, $database);
|
||||
}
|
||||
|
||||
?>
|
24
config/lib/loginManager/lmStates.php
Normal file
24
config/lib/loginManager/lmStates.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/lmStates.php
|
||||
* @version 1.2
|
||||
* @desc States of login manager
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
class lmStates{
|
||||
const LOGIN_FAILED=0;
|
||||
const LOGIN_OK=1;
|
||||
const CAPTCHA_FAILED=2;
|
||||
const BANNED=3;
|
||||
const FORGET_DONE=4;
|
||||
const LOGOUT_DONE=5;
|
||||
|
||||
const AUTH_ID=10;
|
||||
const AUTH_UNAME=11;
|
||||
|
||||
const NOUSER=1;
|
||||
}
|
||||
|
||||
?>
|
14
config/lib/loginManager/lmTwoFactor.php
Normal file
14
config/lib/loginManager/lmTwoFactor.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/lmTwoFactor.php
|
||||
* @version 1.0
|
||||
* @desc second factor auth to LM
|
||||
* @author Fándly Gergő Zoltán 2017
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
interface lmTwoFactor{
|
||||
public function secondFactor($uid);
|
||||
}
|
||||
|
||||
?>
|
44
config/lib/loginManager/lmUtils.php
Normal file
44
config/lib/loginManager/lmUtils.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/lmUtils.php
|
||||
* @desc utilities for correct functioning
|
||||
* @version 1.0
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
class lmUtils{
|
||||
/**
|
||||
* generate a random string with special character
|
||||
* @param int $length length of the requested string
|
||||
* @return string
|
||||
*/
|
||||
public static function randomString($length){
|
||||
$charset="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_-=+\?/.>,<";
|
||||
$charsetLength=strlen($charset);
|
||||
$string="";
|
||||
for($i=0; $i<$length; $i++){
|
||||
$string.=$charset[rand(0, $charsetLength-1)];
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate google ReCaptcha
|
||||
* @param string $secretkey secret key to captcha API
|
||||
* @param string $response response of API
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCaptcha($secretkey, $response){
|
||||
$verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$response);
|
||||
$data=json_decode($verify);
|
||||
if($data->success){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
393
config/lib/loginManager/loginManager.php
Normal file
393
config/lib/loginManager/loginManager.php
Normal file
@ -0,0 +1,393 @@
|
||||
<?php
|
||||
/**
|
||||
* loginManager/loginManager.php
|
||||
* @version 1.1
|
||||
* @desc Easily manage authentication to your system
|
||||
* @author Fándly Gergő Zoltán
|
||||
* @copy 2017 Fándly Gergő Zoltán
|
||||
*/
|
||||
|
||||
/**
|
||||
* NEEDED Database structure:
|
||||
*
|
||||
<?sql
|
||||
CREATE TABLE `users`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`username` varchar(65) NOT NULL default '', /* optional
|
||||
`password` varchar(255) NOT NULL default '',
|
||||
PRIMARY KEY (`id`)
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `login_history`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`user` int(4) UNSIGNED NOT NULL default 1, /* id of nouser
|
||||
`date` timestamp NOT NULL default current_timestamp,
|
||||
`ip` varchar(45) NOT NULL default '0.0.0.0',
|
||||
`auth_token` varchar(65) NOT NULL default '',
|
||||
`user_agent` varchar(500) NOT NULL default '',
|
||||
`success` tinyint(1) NOT NULL default 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`user`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `login_remember`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`user` int(4) UNSIGNED NOT NULL default 0,
|
||||
`remember_token` varchar(65) NOT NULL default '',
|
||||
`until` timestamp NOT NULL default current_timestamp,
|
||||
PRIMARY KEY (`id`),
|
||||
FOREIGN KEY (`user`) REFERENCES users(`id`) ON DELETE CASCADE
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
CREATE TABLE `login_bans`(
|
||||
`id` int(4) UNSIGNED NOT NULL auto_increment,
|
||||
`ip` varchar(45) NOT NULL default '0.0.0.0',
|
||||
`until` timestamp NOT NULL default current_timestamp,
|
||||
PRIMARY KEY (`id`)
|
||||
) CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
INSERT INTO users (`id`, `username`) VALUES (1, 'nouser');
|
||||
?>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Includes
|
||||
*/
|
||||
require("lmStates.php");
|
||||
require("lmConfig.php");
|
||||
require("lmHandler.php");
|
||||
require("lmPassword.php");
|
||||
require("lmTwoFactor.php");
|
||||
require("lmUtils.php");
|
||||
|
||||
|
||||
/*
|
||||
* Class
|
||||
*/
|
||||
class loginManager{
|
||||
//constructor
|
||||
|
||||
/**
|
||||
* building...
|
||||
* @param lmConfig $_config configuration for login Manager
|
||||
* @param lmHandler $_eventHandler handler of events
|
||||
* @param lmPassword $_passwordEngine engine for verifying passwords
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($_config, $_eventHandler, $_passwordEngine, $_twoFactor){
|
||||
$this->config=$_config;
|
||||
$this->eventHandler=$_eventHandler;
|
||||
$this->passwordEngine=$_passwordEngine;
|
||||
$this->twoFactor=$_twoFactor;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//settings
|
||||
|
||||
private $config;
|
||||
private $eventHandler;
|
||||
private $passwordEngine;
|
||||
private $twoFactor;
|
||||
|
||||
|
||||
|
||||
//frontend functions
|
||||
|
||||
/**
|
||||
* initialize session and set its lifetime
|
||||
* @return bool
|
||||
*/
|
||||
public function init(){
|
||||
session_set_cookie_params($this->config->getSessionLifetime());
|
||||
return session_start();
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare for login. Run this on the top of your login page!
|
||||
* @return void
|
||||
*/
|
||||
public function loginPrepare(){
|
||||
$this->passFailedAttempts();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lets start here!
|
||||
* @param int/string @identifier id or username of user
|
||||
* @param string @password cleartext password from input
|
||||
* @param bool $remember save user fot further use
|
||||
* @return void
|
||||
*/
|
||||
public function login($identifier, $password, $remember=false){
|
||||
global $lm_force_captcha;
|
||||
|
||||
if($this->passFailedAttempts()){ //not banned
|
||||
if(isset($lm_force_captcha)){ //check captcha
|
||||
if(!isset($_POST['g-recaptcha-response'])){
|
||||
$captcha_failed=true;
|
||||
$this->addLoginHistory(lmStates::NOUSER, lmStates::LOGIN_FAILED);
|
||||
$this->eventHandler->handle(lmStates::CAPTCHA_FAILED);
|
||||
return;
|
||||
}
|
||||
else{
|
||||
if(!lmUtils::validateCaptcha($this->config->getCaptchaSecretkey(), $_POST['g-recaptcha-response'])){
|
||||
$captcha_failed=true;
|
||||
$this->addLoginHistory(lmStates::NOUSER, lmStates::LOGIN_FAILED);
|
||||
$this->eventHandler->handle(lmStates::CAPTCHA_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($captcha_failed)){
|
||||
if($this->config->isRememberEnabled()){ //check if remembering is enabled
|
||||
if($this->isRememberingUser() && $this->twoFactor->secondFactor($this->isRememberingUser())){ //remembering.
|
||||
$this->permitLogin($this->isRememberingUser()); //good to go!
|
||||
return;
|
||||
}
|
||||
}
|
||||
//proceed with normal login
|
||||
if($this->config->getAuthType()==lmStates::AUTH_UNAME){ //username based authentication
|
||||
$sql=$this->config->getPDO()->prepare("SELECT COUNT(id) AS count, id, password FROM users WHERE username=:identifier and id<>1");
|
||||
}
|
||||
else{
|
||||
$sql=$this->config->getPDO()->prepare("SELECT COUNT(id) AS count, id, password FROM users WHERE id=:identifier and id<>1");
|
||||
}
|
||||
$sql->execute(array(":identifier"=>$identifier));
|
||||
$res=$sql->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($res['count']==0){ //user not existing
|
||||
$this->addLoginHistory(lmStates::NOUSER, lmStates::LOGIN_FAILED);
|
||||
$this->eventHandler->handle(lmStates::LOGIN_FAILED);
|
||||
return;
|
||||
}
|
||||
else{
|
||||
if($this->passwordEngine->verifyPassword($password, $res['password']) && $this->twoFactor->secondFactor($res['id'])){
|
||||
if($this->config->isRememberEnabled()){ //remember... if he wants to be insecure
|
||||
if($remember){
|
||||
$this->rememberUser($res['id']);
|
||||
}
|
||||
}
|
||||
$this->permitLogin($res['id']); //good to go!
|
||||
return;
|
||||
}
|
||||
else{
|
||||
$this->addLoginHistory($res['id'], lmStates::LOGIN_FAILED);
|
||||
$this->eventHandler->handle(lmStates::LOGIN_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* finish it up!
|
||||
* @return void
|
||||
*/
|
||||
public function logout(){
|
||||
$_SESSION=array();
|
||||
session_destroy();
|
||||
setcookie("lm_login_random", NULL, -1);
|
||||
$this->eventHandler->handle(lmStates::LOGOUT_DONE);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* just some formal checking
|
||||
* @return bool
|
||||
*/
|
||||
public function validateLogin(){
|
||||
if(!isset($_SESSION['lm_id'])){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
$sql=$this->config->getPDO()->prepare("SELECT auth_token FROM login_history WHERE user=:id and success=1 ORDER BY id DESC LIMIT 1");
|
||||
$sql->execute(array(":id"=>$_SESSION['lm_id']));
|
||||
$res=$sql->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($res['auth_token']==$this->getSessionKey()){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* do i know you?
|
||||
* @return int
|
||||
*/
|
||||
public function isRememberingUser(){
|
||||
if(!$this->config->isRememberEnabled()){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(is_null($this->getRememberKey())){
|
||||
return NULL;
|
||||
}
|
||||
else{
|
||||
$sql=$this->config->getPDO()->prepare("SELECT COUNT(id) AS count, user FROM login_remember WHERE remember_token=:token and until>:until");
|
||||
$sql->execute(array(":token"=>$this->getRememberKey(), ":until"=>date("Y-m-d H:i:s")));
|
||||
$res=$sql->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($res['count']!=1){
|
||||
$this->addLoginHistory(lmStates::NOUSER, lmStates::LOGIN_FAILED);
|
||||
return NULL;
|
||||
}
|
||||
else{
|
||||
return $res['user'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i don't know you anymore!
|
||||
* @return void
|
||||
*/
|
||||
public function forgetUser(){
|
||||
$sql=$this->config->getPDO()->prepare("UPDATE login_remember SET until=0 WHERE remember_token=:token");
|
||||
$sql->execute(array(":token"=>$this->getRememberKey()));
|
||||
|
||||
setcookie("lm_login_remember", NULL, -1);
|
||||
|
||||
$this->eventHandler->handle(lmStates::FORGET_DONE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* print captcha html code if needed
|
||||
* @param bool $dark use the dark theme, default false
|
||||
* @return void
|
||||
*/
|
||||
public function printCaptcha($force=false, $dark=false){
|
||||
if($this->config->isCaptchaEnabled()){
|
||||
global $lm_force_captcha;
|
||||
if(isset($lm_force_captcha) || $force){
|
||||
if($dark){
|
||||
echo "<div class=\"g-recaptcha\" data-sitekey=\"".$this->config->getCaptchaSitekey()."\" data-theme=\"dark\"></div>";
|
||||
}
|
||||
else{
|
||||
echo "<div class=\"g-recaptcha\" data-sitekey=\"".$this->config->getCaptchaSitekey()."\"></div>";
|
||||
}
|
||||
return;
|
||||
}
|
||||
else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//backend functions
|
||||
|
||||
protected function generateSessionKey(){
|
||||
$random=lmUtils::randomString(32);
|
||||
setcookie("lm_login_random", $random, time()+$this->config->getSessionLifetime());
|
||||
$hash=hash("sha256", $_SERVER['REMOTE_ADDR']."***".$_SERVER['HTTP_USER_AGENT']."***".$random);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
protected function getSessionKey(){
|
||||
if(!isset($_COOKIE['lm_login_random'])){
|
||||
return NULL;
|
||||
}
|
||||
else{
|
||||
$hash=hash("sha256", $_SERVER['REMOTE_ADDR']."***".$_SERVER['HTTP_USER_AGENT']."***".$_COOKIE['lm_login_random']);
|
||||
return $hash;
|
||||
}
|
||||
}
|
||||
|
||||
protected function passFailedAttempts(){
|
||||
//check if no limitations are enabled
|
||||
if(!$this->config->isCaptchaEnabled() && !$this->config->isBanEnabled()){
|
||||
return true; //nothing to do
|
||||
}
|
||||
|
||||
//check if is already banned
|
||||
if($this->config->isBanEnabled()){
|
||||
$sql=$this->config->getPDO()->prepare("SELECT COUNT(id) AS count FROM login_bans WHERE ip=:ip and until>:until");
|
||||
$sql->execute(array(":ip"=>$_SERVER['REMOTE_ADDR'], ":until"=>date("Y-m-d H:i:s")));
|
||||
$res=$sql->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($res['count']!=0){
|
||||
$this->eventHandler->handle(lmStates::BANNED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//count failed attempts
|
||||
$sql=$this->config->getPDO()->prepare("SELECT COUNT(id) AS count FROM login_history WHERE ip=:ip and date>:date and success=0");
|
||||
$sql->execute(array(":ip"=>$_SERVER['REMOTE_ADDR'], ":date"=>date("Y-m-d H:i:s", time()-$this->config->getLook())));
|
||||
$res=$sql->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
//force captcha if case
|
||||
if($res['count']>=$this->config->getCaptchaAfter() && $this->config->isCaptchaEnabled()){
|
||||
global $lm_force_captcha;
|
||||
$lm_force_captcha=true;
|
||||
}
|
||||
|
||||
//bann if case
|
||||
if($res['count']>=$this->config->getBanAfter() && $this->config->isBanEnabled()){
|
||||
$sql=$this->config->getPDO()->prepare("INSERT INTO login_bans (ip, until) VALUES (:ip, :until)");
|
||||
$sql->execute(array(":ip"=>$_SERVER['REMOTE_ADDR'], ":until"=>date("Y-m-d H:i:s", time()+$this->config->getBanTime())));
|
||||
global $lm_banned;
|
||||
$lm_banned=true;
|
||||
$this->eventHandler->handle(lmStates::BANNED);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function addLoginHistory($uid, $success=lmStates::LOGIN_FAILED, $token=""){
|
||||
$sql=$this->config->getPDO()->prepare("INSERT INTO login_history (user, date, ip, auth_token, user_agent, success) VALUES (:user, :date, :ip, :auth_token, :user_agent, :success)");
|
||||
$sql->execute(array(":user"=>$uid, ":date"=>date("Y-m-d H:i:s"), ":ip"=>$_SERVER['REMOTE_ADDR'], ":auth_token"=>$token, ":user_agent"=>$_SERVER['HTTP_USER_AGENT'], ":success"=>$success));
|
||||
return;
|
||||
}
|
||||
|
||||
protected function permitLogin($uid){
|
||||
$token=$this->generateSessionKey();
|
||||
$this->addLoginHistory($uid, lmStates::LOGIN_OK, $token);
|
||||
|
||||
$_SESSION=array();
|
||||
$_SESSION['lm_id']=$uid;
|
||||
|
||||
$this->eventHandler->handle(lmStates::LOGIN_OK, $uid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//functions for remembering
|
||||
protected function generateRememberKey(){
|
||||
$random=lmUtils::randomString(32);
|
||||
setcookie("lm_login_remember", $random, time()+(86000*$this->config->getRememberTime()));
|
||||
$hash=hash("sha256", $_SERVER['REMOTE_ADDR']."***".$_SERVER['HTTP_USER_AGENT']."***".$random);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
protected function getRememberKey(){
|
||||
if(!isset($_COOKIE['lm_login_remember'])){
|
||||
return NULL;
|
||||
}
|
||||
else{
|
||||
$hash=hash("sha256", $_SERVER['REMOTE_ADDR']."***".$_SERVER['HTTP_USER_AGENT']."***".$_COOKIE['lm_login_remember']);
|
||||
return $hash;
|
||||
}
|
||||
}
|
||||
|
||||
protected function rememberUser($uid){
|
||||
$sql=$this->config->getPDO()->prepare("INSERT INTO login_remember (user, remember_token, until) VALUES (:user, :token, :until)");
|
||||
$sql->execute(array(":user"=>$uid, ":token"=>$this->generateRememberKey(), ":until"=>date("Y-m-d H:i:s", time()+(86400*$this->config->getRememberTime()))));
|
||||
return;
|
||||
}
|
||||
}
|
14
config/pubkey.pub
Normal file
14
config/pubkey.pub
Normal file
@ -0,0 +1,14 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAy84FIxzbceSdhxeSGCuh
|
||||
uWnJ9k9Y3GoiHNo7yUXHCWsoFQfqlptXyOzDJvzBetIwUZpyCYTltM6glc/303Z5
|
||||
QGbkJaPEocgE4XumJHlCDTnIa102uUM6+dGpOToQLjFhE/iylfSX4igJdko8v/uK
|
||||
vznq2nfV0PUI/dS7tcCscP2UX7r57lP2vTM/qtW+9IFS4TCVxyecm1hlyo2WFMfb
|
||||
7qmljqO6k7Mt66ImjcZLVOJXZJK8aZa4drOIykKGc2wimMjyyInVqb8lQZfrY9we
|
||||
Xma0+742Ybu05rnq+SpkTVQM8cAEmZ2xKK7Y7SKCkTms0/2pMCJHuMgc8A5zWZwl
|
||||
OFy6Abv+uHTpW36bfJae8zDic+0bLpcn3wpdVdIdqZXszCnBm6EaOFu81Yg2c++V
|
||||
oxccVouUxAiv0xNB22je8+QuofofYulxwKrJiAXg1xTmQShSrKHnDD+KXdomXx91
|
||||
auEnql8EmvUw/n8JzdyzCxaHOifdySac1N4oQorIGKelHb2MakLBeQms7/Aa0AGU
|
||||
LDpDZcClwPQtANJZv0pItefa0mNHFWsxvXNyV4pkq8yOOyeDGyrpAJBAOYblJa52
|
||||
izoJPfOvVdEbkgas9E8fOZ2/dI9gI0TzlmQtXdWW7sSkF8vmCQN/sruR10zTPQdP
|
||||
DP8Fo49h/OOJfYL/OhcEE5MCAwEAAQ==
|
||||
-----END PUBLIC KEY-----
|
Reference in New Issue
Block a user