commit
390864a9b2
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "bl-themes/clean-blog"]
|
||||||
|
path = bl-themes/clean-blog
|
||||||
|
url = git@github.com:bludit-themes/clean-blog.git
|
|
@ -20,6 +20,9 @@ function checkLogin($args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Login->verifyUser($_POST['username'], $_POST['password'])) {
|
if ($Login->verifyUser($_POST['username'], $_POST['password'])) {
|
||||||
|
if (isset($_POST['remember'])) {
|
||||||
|
$Login->setRememberMe($_POST['username']);
|
||||||
|
}
|
||||||
// Renew the token. This token will be the same inside the session for multiple forms.
|
// Renew the token. This token will be the same inside the session for multiple forms.
|
||||||
$Security->generateTokenCSRF();
|
$Security->generateTokenCSRF();
|
||||||
Redirect::page('dashboard');
|
Redirect::page('dashboard');
|
||||||
|
@ -35,16 +38,38 @@ function checkLogin($args)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkRememberMe()
|
||||||
|
{
|
||||||
|
global $Security;
|
||||||
|
global $Login;
|
||||||
|
|
||||||
|
if ($Security->isBlocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Login->verifyUserByRemember()) {
|
||||||
|
$Security->generateTokenCSRF();
|
||||||
|
Redirect::page('dashboard');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$Security->addToBlacklist();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Main before POST
|
// Main before POST
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD']!=='POST') {
|
||||||
|
checkRememberMe();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// POST Method
|
// POST Method
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD']=='POST')
|
if ($_SERVER['REQUEST_METHOD']=='POST') {
|
||||||
{
|
|
||||||
checkLogin($_POST);
|
checkLogin($_POST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
<input name="password" class="uk-width-1-1 uk-form-large" placeholder="<?php $L->p('Password') ?>" type="password">
|
<input name="password" class="uk-width-1-1 uk-form-large" placeholder="<?php $L->p('Password') ?>" type="password">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-form-row">
|
||||||
|
<label><input type="checkbox" name="remember"> Remember me</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="uk-form-row">
|
<div class="uk-form-row">
|
||||||
<button type="submit" class="uk-width-1-1 uk-button uk-button-primary uk-button-large"><?php $Language->p('Login') ?></button>
|
<button type="submit" class="uk-width-1-1 uk-button uk-button-primary uk-button-large"><?php $Language->p('Login') ?></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -110,6 +110,11 @@ define('CLI_STATUS', 'published');
|
||||||
// Cli mode, username for new pages
|
// Cli mode, username for new pages
|
||||||
define('CLI_USERNAME', 'admin');
|
define('CLI_USERNAME', 'admin');
|
||||||
|
|
||||||
|
// Remember me
|
||||||
|
define('REMEMBER_COOKIE_USERNAME', 'BLUDITREMEMBERUSERNAME');
|
||||||
|
define('REMEMBER_COOKIE_TOKEN', 'BLUDITREMEMBERTOKEN');
|
||||||
|
define('REMEMBER_COOKIE_EXPIRE_IN_DAYS', 30);
|
||||||
|
|
||||||
// Filename
|
// Filename
|
||||||
define('FILENAME', 'index.txt');
|
define('FILENAME', 'index.txt');
|
||||||
|
|
||||||
|
@ -202,6 +207,7 @@ include(PATH_HELPERS.'paginator.class.php');
|
||||||
include(PATH_HELPERS.'image.class.php');
|
include(PATH_HELPERS.'image.class.php');
|
||||||
include(PATH_HELPERS.'tcp.class.php');
|
include(PATH_HELPERS.'tcp.class.php');
|
||||||
include(PATH_HELPERS.'dom.class.php');
|
include(PATH_HELPERS.'dom.class.php');
|
||||||
|
include(PATH_HELPERS.'cookie.class.php');
|
||||||
|
|
||||||
if (file_exists(PATH_KERNEL.'bludit.pro.php')) {
|
if (file_exists(PATH_KERNEL.'bludit.pro.php')) {
|
||||||
include(PATH_KERNEL.'bludit.pro.php');
|
include(PATH_KERNEL.'bludit.pro.php');
|
||||||
|
|
|
@ -11,8 +11,7 @@ class dbUsers extends dbJSON
|
||||||
'salt'=> array('inFile'=>false, 'value'=>'!Pink Floyd!Welcome to the machine!'),
|
'salt'=> array('inFile'=>false, 'value'=>'!Pink Floyd!Welcome to the machine!'),
|
||||||
'email'=> array('inFile'=>false, 'value'=>''),
|
'email'=> array('inFile'=>false, 'value'=>''),
|
||||||
'registered'=> array('inFile'=>false, 'value'=>'1985-03-15 10:00'),
|
'registered'=> array('inFile'=>false, 'value'=>'1985-03-15 10:00'),
|
||||||
'tokenEmail'=> array('inFile'=>false, 'value'=>''),
|
'tokenRemember'=> array('inFile'=>false, 'value'=>''),
|
||||||
'tokenEmailTTL'=> array('inFile'=>false, 'value'=>'2009-03-15 14:00'),
|
|
||||||
'tokenAuth'=> array('inFile'=>false, 'value'=>''),
|
'tokenAuth'=> array('inFile'=>false, 'value'=>''),
|
||||||
'tokenAuthTTL'=> array('inFile'=>false, 'value'=>'2009-03-15 14:00'),
|
'tokenAuthTTL'=> array('inFile'=>false, 'value'=>'2009-03-15 14:00'),
|
||||||
'twitter'=> array('inFile'=>false, 'value'=>''),
|
'twitter'=> array('inFile'=>false, 'value'=>''),
|
||||||
|
@ -119,7 +118,7 @@ class dbUsers extends dbJSON
|
||||||
return md5( uniqid().time().DOMAIN );
|
return md5( uniqid().time().DOMAIN );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateEmailToken()
|
public function generateRememberToken()
|
||||||
{
|
{
|
||||||
return $this->generateAuthToken();
|
return $this->generateAuthToken();
|
||||||
}
|
}
|
||||||
|
@ -134,6 +133,13 @@ class dbUsers extends dbJSON
|
||||||
return sha1($password.$salt);
|
return sha1($password.$salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setRememberToken($username, $token)
|
||||||
|
{
|
||||||
|
$args['username'] = $username;
|
||||||
|
$args['tokenRemember'] = $token;
|
||||||
|
return $this->set($args);
|
||||||
|
}
|
||||||
|
|
||||||
public function setPassword($username, $password)
|
public function setPassword($username, $password)
|
||||||
{
|
{
|
||||||
$salt = $this->generateSalt();
|
$salt = $this->generateSalt();
|
||||||
|
@ -170,18 +176,25 @@ class dbUsers extends dbJSON
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTokenEmail($username)
|
// Returns the username with the remember token assigned, FALSE otherwise
|
||||||
|
public function getByRememberToken($token)
|
||||||
{
|
{
|
||||||
// Random hash
|
foreach ($this->db as $username=>$fields) {
|
||||||
$token = $this->generateEmailToken();
|
if ($fields['tokenRemember']==$token) {
|
||||||
$this->db[$username]['tokenEmail'] = $token;
|
return $username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Token time to live, defined by TOKEN_EMAIL_TTL
|
// This function clean all tokens for Remember me
|
||||||
$this->db[$username]['tokenEmailTTL'] = Date::currentOffset(DB_DATE_FORMAT, TOKEN_EMAIL_TTL);
|
// This function is used when some hacker try to use an invalid remember token
|
||||||
|
public function invalidateAllRememberTokens()
|
||||||
// Save the database
|
{
|
||||||
$this->save();
|
foreach ($this->db as $username=>$values) {
|
||||||
return $token;
|
$this->db[$username]['tokenRemember'] = '';
|
||||||
|
}
|
||||||
|
return $this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns array with the username databases filtered by username, FALSE otherwise
|
// Returns array with the username databases filtered by username, FALSE otherwise
|
||||||
|
|
|
@ -2,24 +2,28 @@
|
||||||
|
|
||||||
class Cookie {
|
class Cookie {
|
||||||
|
|
||||||
public static function get($name)
|
public static function get($key)
|
||||||
{
|
{
|
||||||
if(isset($_COOKIE[$name]))
|
if (isset($_COOKIE[$key])) {
|
||||||
{
|
return $_COOKIE[$key];
|
||||||
return($_COOKIE[$name]);
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(false);
|
public static function set($key, $value, $daysToExpire=30)
|
||||||
|
{
|
||||||
|
// The time the cookie expires.
|
||||||
|
// This is a Unix timestamp so is in number of seconds since the epoch.
|
||||||
|
// In other words, you'll most likely set this with the time() function plus the number of seconds before you want it to expire.
|
||||||
|
// Or you might use mktime(). time()+60*60*24*30 will set the cookie to expire in 30 days.
|
||||||
|
// If set to 0, or omitted, the cookie will expire at the end of the session (when the browser closes).
|
||||||
|
$expire = time()+60*60*24*$daysToExpire;
|
||||||
|
setcookie($key, $value, $expire);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function add($name, $value, $expire = 525600)
|
public static function isset($key)
|
||||||
{
|
{
|
||||||
setcookie($name, $value, time() + ($expire * 60));
|
return isset($_COOKIE[$key]);
|
||||||
}
|
|
||||||
|
|
||||||
public static function isSet($name)
|
|
||||||
{
|
|
||||||
return(isset($_COOKIE[$name]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,11 +9,13 @@ class Login {
|
||||||
$this->dbUsers = $dbUsers;
|
$this->dbUsers = $dbUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the username of the user logged
|
||||||
public function username()
|
public function username()
|
||||||
{
|
{
|
||||||
return Session::get('username');
|
return Session::get('username');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the role of the user logged
|
||||||
public function role()
|
public function role()
|
||||||
{
|
{
|
||||||
return Session::get('role');
|
return Session::get('role');
|
||||||
|
@ -26,9 +28,8 @@ class Login {
|
||||||
$username = Session::get('username');
|
$username = Session::get('username');
|
||||||
if (!empty($username)) {
|
if (!empty($username)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else {
|
Log::set(__METHOD__.LOG_SEP.'Session username empty, destroying the session.');
|
||||||
Log::set(__METHOD__.LOG_SEP.'Session username empty, destroy the session.');
|
|
||||||
Session::destroy();
|
Session::destroy();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +50,33 @@ class Login {
|
||||||
Log::set(__METHOD__.LOG_SEP.'User logged, fingerprint: '.$this->fingerPrint());
|
Log::set(__METHOD__.LOG_SEP.'User logged, fingerprint: '.$this->fingerPrint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setRememberMe($username)
|
||||||
|
{
|
||||||
|
$username = Sanitize::html($username);
|
||||||
|
|
||||||
|
// Set the token on the users database
|
||||||
|
$token = $this->dbUsers->generateRememberToken();
|
||||||
|
$this->dbUsers->setRememberToken($username, $token);
|
||||||
|
|
||||||
|
// Set the token on the cookies
|
||||||
|
Cookie::set(REMEMBER_COOKIE_USERNAME, $username, REMEMBER_COOKIE_EXPIRE_IN_DAYS);
|
||||||
|
Cookie::set(REMEMBER_COOKIE_TOKEN, $token, REMEMBER_COOKIE_EXPIRE_IN_DAYS);
|
||||||
|
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'Cookies seted for Remember Me.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invalidateRememberMe()
|
||||||
|
{
|
||||||
|
// Invalidate all tokens on the user databases
|
||||||
|
$this->dbUsers->invalidateAllRememberTokens();
|
||||||
|
|
||||||
|
// Destroy the cookies
|
||||||
|
Cookie::set(REMEMBER_COOKIE_USERNAME, '', -1);
|
||||||
|
Cookie::set(REMEMBER_COOKIE_TOKEN, '', -1);
|
||||||
|
unset($_COOKIE[REMEMBER_COOKIE_USERNAME]);
|
||||||
|
unset($_COOKIE[REMEMBER_COOKIE_TOKEN]);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the username and the password are valid
|
// Check if the username and the password are valid
|
||||||
// Returns TRUE if valid and set the session
|
// Returns TRUE if valid and set the session
|
||||||
// Returns FALSE for invalid username or password
|
// Returns FALSE for invalid username or password
|
||||||
|
@ -82,15 +110,21 @@ class Login {
|
||||||
Log::set(__METHOD__.LOG_SEP.'User logged succeeded by username and password - Username: '.$username);
|
Log::set(__METHOD__.LOG_SEP.'User logged succeeded by username and password - Username: '.$username);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Password incorrect.');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'Password incorrect.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyUserByToken($username, $token)
|
// Check if the user has the cookies and the correct token
|
||||||
|
public function verifyUserByRemember()
|
||||||
{
|
{
|
||||||
|
if (!Cookie::isset(REMEMBER_COOKIE_USERNAME) || !Cookie::isset(REMEMBER_COOKIE_TOKEN)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$username = Cookie::get(REMEMBER_COOKIE_USERNAME);
|
||||||
|
$token = Cookie::get(REMEMBER_COOKIE_TOKEN);
|
||||||
|
|
||||||
$username = Sanitize::html($username);
|
$username = Sanitize::html($username);
|
||||||
$token = Sanitize::html($token);
|
$token = Sanitize::html($token);
|
||||||
|
|
||||||
|
@ -98,55 +132,37 @@ class Login {
|
||||||
$token = trim($token);
|
$token = trim($token);
|
||||||
|
|
||||||
if (empty($username) || empty($token)) {
|
if (empty($username) || empty($token)) {
|
||||||
Log::set(__METHOD__.LOG_SEP.'Username or Token-email empty. Username: '.$username.' - Token-email: '.$token);
|
$this->invalidateRememberMe();
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'Username or Token empty. Username: '.$username.' - Token: '.$token);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($username !== $this->dbUsers->getByRememberToken($token)) {
|
||||||
|
$this->invalidateRememberMe();
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'The user has different token or the token doesn\'t exist.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate user and login
|
||||||
$user = $this->dbUsers->getDb($username);
|
$user = $this->dbUsers->getDb($username);
|
||||||
if($user==false) {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Username does not exist: '.$username);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$currentTime = Date::current(DB_DATE_FORMAT);
|
|
||||||
if($user['tokenEmailTTL']<$currentTime) {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Token-email expired: '.$username);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($token === $user['tokenEmail'])
|
|
||||||
{
|
|
||||||
// Set the user loggued.
|
|
||||||
$this->setLogin($username, $user['role']);
|
$this->setLogin($username, $user['role']);
|
||||||
|
Log::set(__METHOD__.LOG_SEP.'User authenticated via Remember Me.');
|
||||||
// Invalidate the current token.
|
|
||||||
$this->dbUsers->setTokenEmail($username);
|
|
||||||
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'User logged succeeded by Token-email - Username: '.$username);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Log::set(__METHOD__.LOG_SEP.'Token-email incorrect.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fingerPrint()
|
public function fingerPrint()
|
||||||
{
|
{
|
||||||
// User agent
|
|
||||||
$agent = getenv('HTTP_USER_AGENT');
|
$agent = getenv('HTTP_USER_AGENT');
|
||||||
if (empty($agent)) {
|
if (empty($agent)) {
|
||||||
$agent = 'Bludit/2.0 (Mr Nibbler Protocol)';
|
$agent = 'Bludit/2.0 (Mr Nibbler Protocol)';
|
||||||
}
|
}
|
||||||
|
|
||||||
return sha1($agent);
|
return sha1($agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function logout()
|
public function logout()
|
||||||
{
|
{
|
||||||
return Session::destroy();
|
$this->invalidateRememberMe();
|
||||||
|
Session::destroy();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 1620e2f4640cf1dfcd04e2018e6e17b81d7b7e62
|
|
@ -1 +0,0 @@
|
||||||
node_modules
|
|
|
@ -1,11 +0,0 @@
|
||||||
sudo: false
|
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "node"
|
|
||||||
install: npm install
|
|
||||||
script:
|
|
||||||
- npm test
|
|
||||||
- gulp
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- node_modules
|
|
|
@ -1,3 +0,0 @@
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
|
@ -1,136 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<?php
|
|
||||||
include(THEME_DIR_PHP.'head.php')
|
|
||||||
?>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
Theme::plugins('siteBodyBegin')
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!-- Navigation -->
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
|
|
||||||
<div class="container">
|
|
||||||
<a class="navbar-brand" href="<?php echo $Site->url() ?>"><?php echo $Site->title() ?></a>
|
|
||||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<?php echo $Language->get('Menu') ?>
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarResponsive">
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="<?php echo $Site->url() ?>"><?php echo $Language->get('Home') ?></a>
|
|
||||||
</li>
|
|
||||||
<?php
|
|
||||||
foreach ($staticPages as $staticPage) {
|
|
||||||
echo '<li class="nav-item">';
|
|
||||||
echo '<a class="nav-link" href="'.$staticPage->permalink().'">'.$staticPage->title().'</a>';
|
|
||||||
echo '</li>';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<?php
|
|
||||||
if ($WHERE_AM_I=='page') {
|
|
||||||
include(THEME_DIR_PHP.'page.php');
|
|
||||||
} else {
|
|
||||||
include(THEME_DIR_PHP.'home.php');
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8 col-md-10 mx-auto">
|
|
||||||
<ul class="list-inline text-center">
|
|
||||||
<?php
|
|
||||||
if ($Site->twitter()) {
|
|
||||||
echo '
|
|
||||||
<li class="list-inline-item">
|
|
||||||
<a href="'.$Site->twitter().'">
|
|
||||||
<span class="fa-stack fa-lg">
|
|
||||||
<i class="fa fa-circle fa-stack-2x"></i>
|
|
||||||
<i class="fa fa-twitter fa-stack-1x fa-inverse"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
';
|
|
||||||
}
|
|
||||||
if ($Site->facebook()) {
|
|
||||||
echo '
|
|
||||||
<li class="list-inline-item">
|
|
||||||
<a href="'.$Site->facebook().'">
|
|
||||||
<span class="fa-stack fa-lg">
|
|
||||||
<i class="fa fa-circle fa-stack-2x"></i>
|
|
||||||
<i class="fa fa-facebook fa-stack-1x fa-inverse"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
';
|
|
||||||
}
|
|
||||||
if ($Site->github()) {
|
|
||||||
echo '
|
|
||||||
<li class="list-inline-item">
|
|
||||||
<a href="'.$Site->github().'">
|
|
||||||
<span class="fa-stack fa-lg">
|
|
||||||
<i class="fa fa-circle fa-stack-2x"></i>
|
|
||||||
<i class="fa fa-github fa-stack-1x fa-inverse"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
';
|
|
||||||
}
|
|
||||||
if ($Site->codepen()) {
|
|
||||||
echo '
|
|
||||||
<li class="list-inline-item">
|
|
||||||
<a href="'.$Site->codepen().'">
|
|
||||||
<span class="fa-stack fa-lg">
|
|
||||||
<i class="fa fa-circle fa-stack-2x"></i>
|
|
||||||
<i class="fa fa-codepen fa-stack-1x fa-inverse"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
';
|
|
||||||
}
|
|
||||||
if ($Site->instagram()) {
|
|
||||||
echo '
|
|
||||||
<li class="list-inline-item">
|
|
||||||
<a href="'.$Site->instagram().'">
|
|
||||||
<span class="fa-stack fa-lg">
|
|
||||||
<i class="fa fa-circle fa-stack-2x"></i>
|
|
||||||
<i class="fa fa-instagram fa-stack-1x fa-inverse"></i>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</ul>
|
|
||||||
<p class="copyright text-muted"><?php echo $Site->footer() ?> - Powered by <a href="https://www.bludit.com">BLUDIT</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- Scripts -->
|
|
||||||
<?php
|
|
||||||
echo Theme::jquery(); // Jquery from Bludit Core
|
|
||||||
echo Theme::js('vendor/popper/popper.min.js');
|
|
||||||
echo Theme::js('vendor/bootstrap/js/bootstrap.min.js');
|
|
||||||
echo Theme::js('js/clean-blog.min.js');
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
Theme::plugins('siteBodyEnd')
|
|
||||||
?>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
/*
|
|
||||||
This file is loaded before the theme
|
|
||||||
You can add some configuration code in this file
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Background image
|
|
||||||
$backgroundImage = 'https://source.unsplash.com/1600x900/?nature';
|
|
||||||
if ($page->coverImage()===false) {
|
|
||||||
$domImage = DOM::getFirstImage($page->content($fullContent=true));
|
|
||||||
if ($domImage!==false) {
|
|
||||||
$backgroundImage = $domImage;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$backgroundImage = $page->coverImage($absolute=true);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
/*!
|
|
||||||
* Start Bootstrap - Clean Blog v4.0.0-beta (https://startbootstrap.com/template-overviews/clean-blog)
|
|
||||||
* Copyright 2013-2017 Start Bootstrap
|
|
||||||
* Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-clean-blog/blob/master/LICENSE)
|
|
||||||
*/
|
|
||||||
!function(i){"use strict";i("body").on("input propertychange",".floating-label-form-group",function(o){i(this).toggleClass("floating-label-form-group-with-value",!!i(o.target).val())}).on("focus",".floating-label-form-group",function(){i(this).addClass("floating-label-form-group-with-focus")}).on("blur",".floating-label-form-group",function(){i(this).removeClass("floating-label-form-group-with-focus")});if(i(window).width()>1170){var o=i("#mainNav").height();i(window).on("scroll",{previousTop:0},function(){var s=i(window).scrollTop();s<this.previousTop?s>0&&i("#mainNav").hasClass("is-fixed")?i("#mainNav").addClass("is-visible"):i("#mainNav").removeClass("is-visible is-fixed"):s>this.previousTop&&(i("#mainNav").removeClass("is-visible"),s>o&&!i("#mainNav").hasClass("is-fixed")&&i("#mainNav").addClass("is-fixed")),this.previousTop=s})}}(jQuery);
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"theme-data":
|
|
||||||
{
|
|
||||||
"name": "Clean Blog",
|
|
||||||
"description": "Clean Blog ist ein Theme auf der Grundlage von Bootstrap. Es eignet sich insbesondere für Blogs."
|
|
||||||
},
|
|
||||||
"posted-by": "Veröffentlicht von"
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"theme-data":
|
|
||||||
{
|
|
||||||
"name": "Clean Blog",
|
|
||||||
"description": "Clean Blog ist ein Theme auf der Grundlage von Bootstrap. Es eignet sich insbesondere für Blogs."
|
|
||||||
},
|
|
||||||
"posted-by": "Veröffentlicht von"
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"theme-data":
|
|
||||||
{
|
|
||||||
"name": "Clean Blog",
|
|
||||||
"description": "Clean blog is a carefully styled Bootstrap blog theme that is perfect for personal or company blogs."
|
|
||||||
},
|
|
||||||
"posted-by": "Posted by"
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"theme-data":
|
|
||||||
{
|
|
||||||
"name": "Clean Blog",
|
|
||||||
"description": "Tema sencillo y profesional, ideal para blogs personales o para empresas."
|
|
||||||
},
|
|
||||||
"posted-by": "Publicado por"
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"author": "Start Bootstrap",
|
|
||||||
"email": "",
|
|
||||||
"website": "https://startbootstrap.com/template-overviews/clean-blog/",
|
|
||||||
"version": "1.0",
|
|
||||||
"releaseDate": "2017-10-13",
|
|
||||||
"license": "MIT",
|
|
||||||
"compatible": "2.0",
|
|
||||||
"notes": ""
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
<?php
|
|
||||||
echo Theme::charset('utf-8');
|
|
||||||
echo Theme::viewport('width=device-width, initial-scale=1, shrink-to-fit=no');
|
|
||||||
|
|
||||||
// Title and description
|
|
||||||
echo Theme::headTitle();
|
|
||||||
echo Theme::headDescription();
|
|
||||||
|
|
||||||
// Favicon
|
|
||||||
echo Theme::favicon('img/favicon.png');
|
|
||||||
|
|
||||||
// CSS
|
|
||||||
echo Theme::css('vendor/bootstrap/css/bootstrap.min.css');
|
|
||||||
echo Theme::css('css/clean-blog.min.css');
|
|
||||||
echo Theme::css('css/bludit.css');
|
|
||||||
|
|
||||||
// FontAwesome from Bludit Core
|
|
||||||
echo Theme::fontAwesome();
|
|
||||||
|
|
||||||
// Load plugins
|
|
||||||
Theme::plugins('siteHead');
|
|
||||||
?>
|
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
|
|
|
@ -1,55 +0,0 @@
|
||||||
<!-- Page Header -->
|
|
||||||
<header class="masthead" style="background-image: url('<?php echo $backgroundImage ?>')">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8 col-md-10 mx-auto">
|
|
||||||
<div class="site-heading">
|
|
||||||
<h1><?php echo $Site->title() ?></h1>
|
|
||||||
<span class="subheading"><?php echo $Site->description() ?></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8 col-md-10 mx-auto">
|
|
||||||
|
|
||||||
<!-- Content -->
|
|
||||||
<?php
|
|
||||||
foreach ($content as $page):
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="post-preview">
|
|
||||||
<a href="<?php echo $page->permalink() ?>">
|
|
||||||
<h2 class="post-title"><?php echo $page->title() ?></h2>
|
|
||||||
<h3 class="post-subtitle"><?php echo $page->description() ?></h3>
|
|
||||||
</a>
|
|
||||||
<p class="post-meta"><?php echo $Language->get('Posted by').' '.$page->user('username').' - '.$page->date() ?></p>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
endforeach
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!-- Pager -->
|
|
||||||
<div class="clearfix">
|
|
||||||
<?php
|
|
||||||
if(Paginator::showPrev()) {
|
|
||||||
echo '<a class="btn btn-secondary float-left" href="'.Paginator::prevPageUrl().'">← '.$Language->get('Previous page').'</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Paginator::showNext()) {
|
|
||||||
echo '<a class="btn btn-secondary float-right" href="'.Paginator::nextPageUrl().'">'.$Language->get('Next page').' →</a>';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
|
@ -1,27 +0,0 @@
|
||||||
<!-- Page Header -->
|
|
||||||
<header class="masthead" style="background-image: url('<?php echo $backgroundImage ?>')">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8 col-md-10 mx-auto">
|
|
||||||
<div class="post-heading">
|
|
||||||
<h1><?php echo $page->title() ?></h1>
|
|
||||||
<h2 class="subheading"><?php echo $page->description() ?></h2>
|
|
||||||
<p class="meta"><?php echo $Language->get('Posted by').' '.$page->user('username').' - '.$page->date() ?></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- Post Content -->
|
|
||||||
<article>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8 col-md-10 mx-auto">
|
|
||||||
<?php echo $page->content($fullContent=true) ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<hr>
|
|
File diff suppressed because one or more lines are too long
|
@ -1,2 +0,0 @@
|
||||||
html{box-sizing:border-box;font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}*,::after,::before{box-sizing:inherit}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}
|
|
||||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -37,7 +37,7 @@ h2 {
|
||||||
}
|
}
|
||||||
/* PAGES */
|
/* PAGES */
|
||||||
|
|
||||||
article.page:not(:last-child) {
|
article.page {
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue