mirror of
https://github.com/sorenpeter/timeline.git
synced 2025-12-15 10:57:01 +00:00
Merge branch 'main' into 34-different-time-zone-is-being-used-in-new-twts-and-in-replies
This commit is contained in:
commit
e607df37a1
24 changed files with 424 additions and 363 deletions
|
|
@ -84,6 +84,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
## 🐞 Bugs to fix
|
## 🐞 Bugs to fix
|
||||||
|
|
||||||
- [x] (2024-11-30) Fix issues with parsing markdown vs. twtxt syntax (replaceed slimdown with Parsedown, supporting lists, block quotes, code/blocks, links, images)
|
- [x] (2024-11-30) Fix issues with parsing markdown vs. twtxt syntax (replaceed slimdown with Parsedown, supporting lists, block quotes, code/blocks, links, images)
|
||||||
|
- [x] (2024-12-26) Extend session duration for 30 days
|
||||||
|
- [ ] (2024-12-26) Read the config.ini in a centralized place and add validations useful when installing or upgrading `timeline`.
|
||||||
|
|
||||||
|
|
||||||
## 🚀 Features to code
|
## 🚀 Features to code
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
2024.12.06
|
2024.12.26
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ require_once('session.php');
|
||||||
|
|
||||||
if (!isset($_SESSION['valid_session'])) {
|
if (!isset($_SESSION['valid_session'])) {
|
||||||
$secretKey = $config['totp_secret'];
|
$secretKey = $config['totp_secret'];
|
||||||
$cookieVal = decodeCookie($secretKey);
|
$cookieVal = isSavedCookieValid($secretKey);
|
||||||
|
|
||||||
if ($cookieVal === false) { # Valid cookie ?
|
if ($cookieVal === false) { # Valid cookie ?
|
||||||
header('Location: login.php');
|
header('Location: login.php');
|
||||||
|
|
@ -58,12 +58,14 @@ if (isset($_POST['submit'])) {
|
||||||
} else { ?>
|
} else { ?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>twtxt</title>
|
<title>twtxt</title>
|
||||||
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1><a href=".">twtxt</a></h1>
|
<h1><a href=".">twtxt</a></h1>
|
||||||
<form method="POST" class="column">
|
<form method="POST" class="column">
|
||||||
|
|
@ -78,5 +80,6 @@ if (isset($_POST['submit'])) {
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
<?php
|
|
||||||
$config = parse_ini_file('private/config.ini');
|
|
||||||
const COOKIE_NAME = 'remember_user';
|
|
||||||
const ENCRYPTION_METHOD = 'aes-256-cbc';
|
|
||||||
|
|
||||||
session_start([
|
|
||||||
'name' => 'twtxt_session',
|
|
||||||
'use_strict_mode' => true,
|
|
||||||
'cookie_httponly' => true,
|
|
||||||
'cookie_secure' => $config['secure_cookies'],
|
|
||||||
'sid_length' => 64,
|
|
||||||
'sid_bits_per_character' => 6,
|
|
||||||
'cookie_samesite' => 'Strict', // Not compatible with PHP lower than 7.3
|
|
||||||
]);
|
|
||||||
|
|
||||||
function has_valid_session() {
|
|
||||||
$config = parse_ini_file('private/config.ini');
|
|
||||||
$secretKey = $config['password'];
|
|
||||||
|
|
||||||
if (isset($_SESSION['valid_session'])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$cookieVal = decodeCookie($secretKey);
|
|
||||||
if ($cookieVal === false) {
|
|
||||||
#echo "Invalid cookie";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function encrypt(string $data, string $key, string $method): string {
|
|
||||||
$ivSize = openssl_cipher_iv_length($method);
|
|
||||||
$iv = openssl_random_pseudo_bytes($ivSize);
|
|
||||||
$encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
|
|
||||||
# PHP 8.2 - Deprecated: implode():
|
|
||||||
# Passing null to parameter #1 ($separator) of type array|string is deprecated
|
|
||||||
//$encrypted = strtoupper(implode(null, unpack('H*', $encrypted)));
|
|
||||||
$encrypted = strtoupper(implode(unpack('H*', $encrypted)));
|
|
||||||
|
|
||||||
return $encrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decrypt(string $data, string $key, string $method): string {
|
|
||||||
$data = pack('H*', $data);
|
|
||||||
$ivSize = openssl_cipher_iv_length($method);
|
|
||||||
$iv = openssl_random_pseudo_bytes($ivSize);
|
|
||||||
$decrypted = openssl_decrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
|
|
||||||
|
|
||||||
return trim($decrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveLoginSuccess($secretKey) {
|
|
||||||
// Set a cookie to remember the user
|
|
||||||
$_SESSION['valid_session'] = true;
|
|
||||||
|
|
||||||
// Set a cookie value to remember the user
|
|
||||||
$encoded_cookie_value = generateCookieValue('admin', $secretKey);
|
|
||||||
$cookie_expiry = time() + (30 * 24 * 60 * 60); // 30 days
|
|
||||||
|
|
||||||
$config = parse_ini_file('private/config.ini');
|
|
||||||
|
|
||||||
setcookie(COOKIE_NAME, $encoded_cookie_value, [
|
|
||||||
'expires' => $cookie_expiry,
|
|
||||||
'secure' => $config['secure_cookies'],
|
|
||||||
'httponly' => true,
|
|
||||||
'samesite' => 'Strict',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateCookieValue($username, $secretKey) {
|
|
||||||
$key = bin2hex($secretKey);
|
|
||||||
|
|
||||||
$encrypted = encrypt($username, $key, ENCRYPTION_METHOD);
|
|
||||||
return $encrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decodeCookie($secretKey) {
|
|
||||||
// Retrieve the encoded cookie name
|
|
||||||
if (!isset($_COOKIE[COOKIE_NAME])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$encoded_cookie_value = $_COOKIE[COOKIE_NAME];
|
|
||||||
$key = bin2hex($secretKey);
|
|
||||||
|
|
||||||
$config = parse_ini_file('private/config.ini');
|
|
||||||
|
|
||||||
// Extend expiry by 30 days
|
|
||||||
$cookie_expiry = time() + (30 * 24 * 60 * 60);
|
|
||||||
setcookie(COOKIE_NAME, $encoded_cookie_value, [
|
|
||||||
'expires' => $cookie_expiry,
|
|
||||||
'secure' => $config['secure_cookies'],
|
|
||||||
'httponly' => true,
|
|
||||||
'samesite' => 'Strict',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$decrypted = decrypt($encoded_cookie_value, $key, ENCRYPTION_METHOD);
|
|
||||||
return $decrypted;
|
|
||||||
}
|
|
||||||
|
|
@ -30,19 +30,21 @@ $routes = [
|
||||||
'/new' => 'new_twt.php',
|
'/new' => 'new_twt.php',
|
||||||
'/add' => 'add_feed.php',
|
'/add' => 'add_feed.php',
|
||||||
'/following' => 'following.php',
|
'/following' => 'following.php',
|
||||||
//'/refresh' => 'load_twt_files.php',
|
|
||||||
'/refresh' => 'refresh.php',
|
'/refresh' => 'refresh.php',
|
||||||
'/login' => 'login.php',
|
'/login' => 'login.php',
|
||||||
'/logout' => 'logout.php',
|
'/logout' => 'logout.php',
|
||||||
'/profile' => 'profile.php',
|
'/profile' => 'profile.php',
|
||||||
'/replies' => 'replies.php',
|
'/replies' => 'replies.php',
|
||||||
'/gallery' => 'gallery.php',
|
'/gallery' => 'gallery.php',
|
||||||
//'/profile/([a-zA-Z0-9_-]+)' => 'profile.php',
|
|
||||||
'/conv/([a-zA-Z0-9]{7})' => 'conv.php', // matches only twtHash of exactly 7 alphanumeric characters
|
'/conv/([a-zA-Z0-9]{7})' => 'conv.php', // matches only twtHash of exactly 7 alphanumeric characters
|
||||||
'/post/([a-zA-Z0-9]{7})' => 'post.php', // matches only twtHash of exactly 7 alphanumeric characters
|
'/post/([a-zA-Z0-9]{7})' => 'post.php', // matches only twtHash of exactly 7 alphanumeric characters
|
||||||
//'/thumb' => 'thumb.php',
|
|
||||||
'/upload' => 'upload_img.php',
|
'/upload' => 'upload_img.php',
|
||||||
'/webmention' => 'webmention_endpoint.php',
|
'/webmention' => 'webmention_endpoint.php',
|
||||||
|
//'/thumb' => 'thumb.php',
|
||||||
|
//'/profile/([a-zA-Z0-9_-]+)' => 'profile.php',
|
||||||
|
|
||||||
|
# Debug endpoints
|
||||||
|
'/test_login' => 'test_login.php',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Loop through the defined routes and try to match the request URI
|
// Loop through the defined routes and try to match the request URI
|
||||||
|
|
|
||||||
138
libs/persistent_session.php
Normal file
138
libs/persistent_session.php
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?php
|
||||||
|
$config = parse_ini_file('private/config.ini');
|
||||||
|
|
||||||
|
# TODO: Move this verification to another file
|
||||||
|
$required_keys = ['secret_key', 'password', 'totp_secret', 'totp_digits', 'secure_cookies'];
|
||||||
|
$missing_keys = array_filter($required_keys, fn($key) => !isset($config[$key]));
|
||||||
|
|
||||||
|
if (!empty($missing_keys)) {
|
||||||
|
die('Missing required keys in config.ini: ' . implode(', ', $missing_keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($config['secret_key']) < 32) {
|
||||||
|
die('Secret key in config.ini must be at least 32 characters long');
|
||||||
|
}
|
||||||
|
|
||||||
|
const COOKIE_NAME = 'timeline_login';
|
||||||
|
const ENCRYPTION_METHOD = 'aes-256-cbc';
|
||||||
|
const EXPIRATION_DAYS = 30;
|
||||||
|
|
||||||
|
const HASH_LENGTH = 128;
|
||||||
|
const HASH_ALGORITHM = 'sha512';
|
||||||
|
|
||||||
|
session_start([
|
||||||
|
'name' => 'timeline_session',
|
||||||
|
'use_strict_mode' => true,
|
||||||
|
'cookie_httponly' => true,
|
||||||
|
'cookie_secure' => $config['secure_cookies'],
|
||||||
|
'sid_length' => 64,
|
||||||
|
'sid_bits_per_character' => 6,
|
||||||
|
'cookie_samesite' => 'Strict', # Not compatible with PHP < 7.3
|
||||||
|
]);
|
||||||
|
|
||||||
|
function hasValidSession(): bool {
|
||||||
|
# If short lived session is valid
|
||||||
|
if (isset($_SESSION['session_expiration']) && $_SESSION['session_expiration'] > time()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO: Check if the session has expired
|
||||||
|
# Add more protection to prevent session fixation
|
||||||
|
# https://owasp.org/www-community/attacks/Session_fixation
|
||||||
|
|
||||||
|
# Otherwise, check the persistent cookie
|
||||||
|
return isSavedCookieValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookieData() {
|
||||||
|
if (!isset($_COOKIE[COOKIE_NAME])) {
|
||||||
|
#echo "Cookie " . COOKIE_NAME . " not found";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = base64_decode($_COOKIE[COOKIE_NAME]);
|
||||||
|
#var_dump($raw);
|
||||||
|
|
||||||
|
# Cookie should be at least the size of the hash length.
|
||||||
|
# If it's not, we can just bail out
|
||||||
|
if (strlen($raw) < HASH_LENGTH) {
|
||||||
|
#echo "Didn't get minimum length";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = parse_ini_file('private/config.ini');
|
||||||
|
|
||||||
|
# The cookie data contains the actual data w/ the hash concatenated to the end,
|
||||||
|
# since the hash is a fixed length, we can extract the last hash_length chars
|
||||||
|
# to get the hash.
|
||||||
|
$hash = substr($raw, strlen($raw) - HASH_LENGTH, HASH_LENGTH);
|
||||||
|
$data = substr($raw, 0, - (HASH_LENGTH));
|
||||||
|
|
||||||
|
# Calculate the expected hash from the data. If the data has not been
|
||||||
|
# tampered with, $hash and $hash_calculated will be the same
|
||||||
|
$hash_calculated = hash_hmac(HASH_ALGORITHM, $data, $config['secret_key']);
|
||||||
|
|
||||||
|
if ($hash_calculated !== $hash) {
|
||||||
|
#echo "Different HASH. Tempered data?";
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intval($data) < time()) {
|
||||||
|
#echo "Cookie expired";
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePersistentCookie() {
|
||||||
|
$config = parse_ini_file('private/config.ini');
|
||||||
|
|
||||||
|
$cookieExpiry = EXPIRATION_DAYS * 24 * 60 * 60 + time(); # X days
|
||||||
|
#$cookieExpiry = 10 + time(); # Debug value - 10 seconds
|
||||||
|
|
||||||
|
# Calculate a hash for the data and append it to the end of the data string
|
||||||
|
$cookieValue = strval($cookieExpiry);
|
||||||
|
|
||||||
|
$hash = hash_hmac(HASH_ALGORITHM, $cookieValue, $config['secret_key']);
|
||||||
|
$cookieValue .= $hash;
|
||||||
|
$cookieValue = base64_encode($cookieValue);
|
||||||
|
|
||||||
|
# Also create the short-timed session
|
||||||
|
$_SESSION['session_expiration'] = $cookieExpiry;
|
||||||
|
|
||||||
|
return setcookie(COOKIE_NAME, $cookieValue, [
|
||||||
|
'expires' => $cookieExpiry,
|
||||||
|
'secure' => $config['secure_cookies'],
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Strict',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveLogin() {
|
||||||
|
makePersistentCookie();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSavedCookieValid() {
|
||||||
|
$cookieExpiry = getCookieData();
|
||||||
|
|
||||||
|
if ($cookieExpiry === false) {
|
||||||
|
deletePersistentCookie();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
# @eapl As it's implemented, the user has to login again in 30 days
|
||||||
|
# since the first login, which I think is a good compromise.
|
||||||
|
|
||||||
|
# Refresh session
|
||||||
|
$_SESSION['session_expiration'] = intval($cookieExpiry);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deletePersistentCookie() {
|
||||||
|
if (isset($_COOKIE[COOKIE_NAME])) {
|
||||||
|
unset($_COOKIE[COOKIE_NAME]);
|
||||||
|
setcookie(COOKIE_NAME, '', time() - 3600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +1,36 @@
|
||||||
<?php
|
<?php
|
||||||
require_once('libs/TOTP.php');
|
require_once 'libs/TOTP.php';
|
||||||
|
require_once 'libs/persistent_session.php';
|
||||||
|
|
||||||
$config = parse_ini_file('private/config.ini');
|
$config = parse_ini_file('private/config.ini');
|
||||||
$password = $config['password'];
|
$passwordInConfig = $config['password'];
|
||||||
|
|
||||||
session_start();
|
function checkValidSessionOrRedirectToLogin() {
|
||||||
|
if (!hasValidSession()) {
|
||||||
|
header('Location: ./login');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_POST['submit_pass']) && $_POST['pass'])
|
if (isset($_POST['submit_pass']) && $_POST['pass']) {
|
||||||
{
|
$passwordInForm = $_POST['pass'];
|
||||||
$pass = $_POST['pass'];
|
|
||||||
|
|
||||||
// @eapl.me 2023-11-23 - I'm trying to add support to passwords
|
if ($passwordInForm == $passwordInConfig) {
|
||||||
// and TOTP (passwordless). So, in the Pwd field you can enter
|
$_SESSION['password'] = $passwordInForm;
|
||||||
// the password, or the current TOTP
|
saveLogin();
|
||||||
if ($pass == $password)
|
} elseif ($isCodeValid = verifyTOTP(
|
||||||
{
|
$config['totp_secret'],
|
||||||
$_SESSION['password'] = $pass;
|
$passwordInForm,
|
||||||
}
|
intval($config['totp_digits'])
|
||||||
elseif ($isCodeValid = verifyTOTP(
|
)) {
|
||||||
$config['totp_secret'], $pass, intval($config['totp_digits']))
|
$_SESSION['password'] = 'valid_totp';
|
||||||
)
|
saveLogin();
|
||||||
{
|
} else {
|
||||||
// If TOTP is valid, assume that we entered the Password
|
$error = 'Incorrect Password';
|
||||||
$_SESSION['password'] = $password;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$error = "Incorrect Password";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check for an empty password
|
||||||
|
if (isset($_POST['submit_pass']) && !$_POST['pass']) {
|
||||||
|
$error = 'Type a password';
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class TwtxtFile {
|
||||||
public $mainURL = ''; // First found URL
|
public $mainURL = ''; // First found URL
|
||||||
public $URLs = [];
|
public $URLs = [];
|
||||||
public $nick = '';
|
public $nick = '';
|
||||||
|
public $domain = '';
|
||||||
public $avatar = '';
|
public $avatar = '';
|
||||||
public $emoji = '';
|
public $emoji = '';
|
||||||
public $description = '';
|
public $description = '';
|
||||||
|
|
@ -37,6 +38,7 @@ class Twt {
|
||||||
public $avatar;
|
public $avatar;
|
||||||
public $emoji;
|
public $emoji;
|
||||||
public $nick;
|
public $nick;
|
||||||
|
public $domain;
|
||||||
public $mainURL;
|
public $mainURL;
|
||||||
public $images = [];
|
public $images = [];
|
||||||
public $tags = [];
|
public $tags = [];
|
||||||
|
|
@ -456,8 +458,7 @@ function getTwtsFromTwtxtString($url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up nick if set to something like `@soren@darch.dk` instead of just `soren`
|
// Clean up nick if set to something like `@soren@darch.dk` instead of just `soren` - mosty for (re)feeds from Mastodon etc.
|
||||||
// mosty for (re)feeds from Mastodon etc.
|
|
||||||
if (str_contains($twtxtData->nick, "@")) {
|
if (str_contains($twtxtData->nick, "@")) {
|
||||||
$str = $twtxtData->nick;
|
$str = $twtxtData->nick;
|
||||||
$str = ltrim($str, "@");
|
$str = ltrim($str, "@");
|
||||||
|
|
@ -465,17 +466,25 @@ function getTwtsFromTwtxtString($url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback for nick and url if not set in twtxt.txt
|
// Fallback for nick and url if not set in twtxt.txt
|
||||||
// TODO: Use nick from local follow list as fallback?
|
|
||||||
if ($twtxtData->nick === "") {
|
if ($twtxtData->nick === "") {
|
||||||
$str = parse_url($url, PHP_URL_HOST);
|
$str = parse_url($url, PHP_URL_HOST);
|
||||||
$str = str_replace("www.", "", $str);
|
$str = str_replace("www.", "", $str);
|
||||||
$str = explode(".", $str)[0]; // take the first [0] from splitting the host at "."
|
//$str = explode(".", $str)[0]; // take the first [0] from splitting the host at "."
|
||||||
$twtxtData->nick = $str;
|
$twtxtData->nick = $str;
|
||||||
}
|
}
|
||||||
if ($twtxtData->mainURL === "") {
|
if ($twtxtData->mainURL === "") {
|
||||||
$twtxtData->mainURL = $url;
|
$twtxtData->mainURL = $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use only nick as handle if nick and domain is the same
|
||||||
|
$twtxtData->domain = parse_url($twtxtData->mainURL, PHP_URL_HOST);
|
||||||
|
|
||||||
|
if ($twtxtData->nick === $twtxtData->domain) {
|
||||||
|
$twtxtData->domain = "";
|
||||||
|
} else {
|
||||||
|
$twtxtData->domain = "@".$twtxtData->domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!str_starts_with($currentLine, '#')) {
|
if (!str_starts_with($currentLine, '#')) {
|
||||||
$explodedLine = explode("\t", $currentLine);
|
$explodedLine = explode("\t", $currentLine);
|
||||||
|
|
@ -550,6 +559,7 @@ function getTwtsFromTwtxtString($url) {
|
||||||
$twt->emoji = $twtxtData->emoji;
|
$twt->emoji = $twtxtData->emoji;
|
||||||
$twt->nick = $twtxtData->nick;
|
$twt->nick = $twtxtData->nick;
|
||||||
$twt->mainURL = $twtxtData->mainURL;
|
$twt->mainURL = $twtxtData->mainURL;
|
||||||
|
$twt->domain = $twtxtData->domain;
|
||||||
|
|
||||||
$twtxtData->twts[$timestamp] = $twt;
|
$twtxtData->twts[$timestamp] = $twt;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
// TODO: fix it so if List -> Selected for both public and private lists
|
// TODO: fix it so if List -> Selected for both public and private lists
|
||||||
|
|
||||||
if (isset($_SESSION['password'])) {
|
if (isset($_SESSION['password'])) {
|
||||||
if($_SESSION['password']=="$password") { // Hacky login
|
if ($_SESSION['password'] == "$passwordInConfig") { // Hacky login
|
||||||
|
|
||||||
// Private lists
|
// Private lists
|
||||||
echo "<option disabled>Private Lists:</option>";
|
echo "<option disabled>Private Lists:</option>";
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
// TODO: fix it so if List -> Selected for both public and private lists
|
// TODO: fix it so if List -> Selected for both public and private lists
|
||||||
|
|
||||||
if (isset($_SESSION['password'])) {
|
if (isset($_SESSION['password'])) {
|
||||||
if($_SESSION['password']=="$password") { // Hacky login
|
if ($_SESSION['password'] == "$passwordInConfig") { // Hacky login
|
||||||
|
|
||||||
// Private lists
|
// Private lists
|
||||||
echo "<option disabled>Private Lists:</option>";
|
echo "<option disabled>Private Lists:</option>";
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ if ($is_gallery) {
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<a href="<?=$profileURL?>" class="author">
|
<a href="<?=$profileURL?>" class="author">
|
||||||
<strong><?=$profile->nick?></strong>@<?=parse_url($profile->mainURL, PHP_URL_HOST);?>
|
<strong>@<?=$profile->nick?></strong><?=$profile->domain?>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<p><?=$profile->description?></p>
|
<p><?=$profile->description?></p>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</a>
|
</a>
|
||||||
<div>
|
<div>
|
||||||
<a href="<?=$baseURL?>/profile?url=<?=$twt->mainURL?>" class="author">
|
<a href="<?=$baseURL?>/profile?url=<?=$twt->mainURL?>" class="author">
|
||||||
<strong><?=$twt->nick?></strong>@<?=parse_url($twt->mainURL, PHP_URL_HOST);?>
|
<strong>@<?=$twt->nick?></strong><?=$twt->domain?>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="twt-msg">
|
<div class="twt-msg">
|
||||||
|
|
@ -49,9 +49,8 @@
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<?php }
|
<?php }
|
||||||
|
require_once 'libs/session.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['password'])) {
|
if (!hasValidSession()) {
|
||||||
echo '<center><a href="mailto:' . $config['email'] . '?subject=RE: ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . '" class="button">Comment via email</a></center>';
|
echo '<center><a href="mailto:' . $config['email'] . '?subject=RE: ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . '" class="button">Comment via email</a></center>';
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
require_once "libs/twtxt.php";
|
require_once "libs/twtxt.php";
|
||||||
|
|
||||||
// Send webmentions (TODO: move to it own file?)
|
// Send webmentions
|
||||||
$new_mentions = getMentionsFromTwt($twt);
|
$new_mentions = getMentionsFromTwt($twt);
|
||||||
|
|
||||||
foreach ($new_mentions as $mention) {
|
foreach ($new_mentions as $mention) {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,15 @@ webmentions_txt_path = "./mentions.txt"
|
||||||
public_webmentions = "https://example.com/timeline/mentions.txt"
|
public_webmentions = "https://example.com/timeline/mentions.txt"
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
; Generate it with the TOTP module
|
; Secret key to encrypt cookies of at least 256-bit (32 characters)
|
||||||
|
; Create one here: https://randomkeygen.com (CodeIgniter Encryption Keys)
|
||||||
|
secret_key = ""
|
||||||
|
|
||||||
|
; Simple password
|
||||||
|
password = "change_me"
|
||||||
|
|
||||||
|
; A dynamic password (TOTP) changing every 30 seconds
|
||||||
|
; Use a TOTP client with support for 10 digits like Aegis (Android)
|
||||||
totp_digits = 10
|
totp_digits = 10
|
||||||
totp_secret = "1234567890"
|
totp_secret = "1234567890"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,13 @@ require_once('libs/twtxt.php');
|
||||||
require_once('libs/hash.php');
|
require_once('libs/hash.php');
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once("partials/base.php");
|
require_once "partials/base.php";
|
||||||
|
require_once "libs/session.php";
|
||||||
|
|
||||||
|
checkValidSessionOrRedirectToLogin();
|
||||||
|
|
||||||
$config = parse_ini_file('private/config.ini');
|
$config = parse_ini_file('private/config.ini');
|
||||||
|
|
||||||
if (!isset($_SESSION['password'])) {
|
|
||||||
header('Location: ./login');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$max_execution_time = intval($config['max_execution_time']);
|
$max_execution_time = intval($config['max_execution_time']);
|
||||||
if ($max_execution_time < 1) {
|
if ($max_execution_time < 1) {
|
||||||
$max_execution_time = 1;
|
$max_execution_time = 1;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
require_once('partials/base.php');
|
require_once 'partials/base.php';
|
||||||
require_once('partials/webfinger_lookup.php');
|
require_once 'partials/webfinger_lookup.php';
|
||||||
|
require_once 'libs/session.php';
|
||||||
|
|
||||||
|
checkValidSessionOrRedirectToLogin();
|
||||||
|
|
||||||
// TODO: Give a warning if the file is not found
|
// TODO: Give a warning if the file is not found
|
||||||
$config = parse_ini_file('private/config.ini');
|
$config = parse_ini_file('private/config.ini');
|
||||||
|
|
@ -13,18 +16,6 @@ if ($config['debug_mode']) {
|
||||||
|
|
||||||
$txt_file_path = $config['txt_file_path'];
|
$txt_file_path = $config['txt_file_path'];
|
||||||
|
|
||||||
if (!isset($_SESSION['password'])) {
|
|
||||||
header('Location: ./login');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (!has_valid_session()) {
|
|
||||||
header('Location: login.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (isset($_POST['url'])) {
|
if (isset($_POST['url'])) {
|
||||||
$url = trim(filter_input(INPUT_POST, 'url'));
|
$url = trim(filter_input(INPUT_POST, 'url'));
|
||||||
$nick = trim(filter_input(INPUT_POST, 'nick'));
|
$nick = trim(filter_input(INPUT_POST, 'nick'));
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ include 'partials/header.php';
|
||||||
<!-- <th></th> -->
|
<!-- <th></th> -->
|
||||||
<th>Nick</th>
|
<th>Nick</th>
|
||||||
<th>URL</th>
|
<th>URL</th>
|
||||||
<?php if(isset($_SESSION['password']) && $_SESSION['password']=="$password") { ?>
|
<?php if (isset($_SESSION['password']) && $_SESSION['password'] == "$passwordInConfig") { ?>
|
||||||
<th>Time ago</th>
|
<th>Time ago</th>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -29,11 +29,13 @@ include 'partials/header.php';
|
||||||
<td><a href="<?= $baseURL ?>/profile?url=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td>
|
<td><a href="<?= $baseURL ?>/profile?url=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td>
|
||||||
<!-- <td><a href="/?twt=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td> -->
|
<!-- <td><a href="/?twt=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td> -->
|
||||||
<td><?= $currentFollower[1] ?>
|
<td><?= $currentFollower[1] ?>
|
||||||
<!-- <?php //if ($validSession) { ?> -->
|
<!-- <?php //if ($validSession) {
|
||||||
|
?> -->
|
||||||
<!-- <a href="?remove_url=<?= $currentFollower[1] ?>">Remove</a> -->
|
<!-- <a href="?remove_url=<?= $currentFollower[1] ?>">Remove</a> -->
|
||||||
<!-- <?php // } ?> -->
|
<!-- <?php // }
|
||||||
|
?> -->
|
||||||
</td>
|
</td>
|
||||||
<?php if(isset($_SESSION['password']) && $_SESSION['password']=="$password") { ?>
|
<?php if (isset($_SESSION['password']) && $_SESSION['password'] == "$passwordInConfig") { ?>
|
||||||
<td>
|
<td>
|
||||||
<?php
|
<?php
|
||||||
// Test first if URL is a valid feed:
|
// Test first if URL is a valid feed:
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,12 @@ if (!empty($_GET['profile'])) { // Show twts for some user (Profile view)
|
||||||
|
|
||||||
// Load twts, taking $paginateTwts into consideration
|
// Load twts, taking $paginateTwts into consideration
|
||||||
require_once 'partials/base.php';
|
require_once 'partials/base.php';
|
||||||
|
require_once 'libs/session.php';
|
||||||
|
|
||||||
$title = "Timeline for ".$title;
|
$title = "Timeline for $title";
|
||||||
|
|
||||||
|
// Redirect guests to Profile view, if URL isn't set to home twtxt.txt
|
||||||
// Redirect guests to Profile view, if url not set til home twtxt.txt
|
if (!hasValidSession() && isset($_GET['url'])) {
|
||||||
|
|
||||||
if (!isset($_SESSION['password']) && (isset($_GET['url']))) {
|
|
||||||
if ($_GET['url'] != $config['public_txt_url']) {
|
if ($_GET['url'] != $config['public_txt_url']) {
|
||||||
header('Location: ./profile');
|
header('Location: ./profile');
|
||||||
exit();
|
exit();
|
||||||
|
|
@ -33,10 +32,9 @@ if (!isset($_SESSION['password']) && (isset($_GET['url']))) {
|
||||||
|
|
||||||
include_once 'partials/header.php';
|
include_once 'partials/header.php';
|
||||||
|
|
||||||
if (isset($_SESSION['password'])) {
|
if (hasValidSession()) {
|
||||||
include 'views/new_twt.php'; // TODO: Split up new_twt into a view and a partial
|
include 'views/new_twt.php'; // TODO: Split up new_twt into a view and a partial
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
echo '<center><h2>Timeline</h2>';
|
echo '<center><h2>Timeline</h2>';
|
||||||
|
|
||||||
echo '<p>Recent posts from feeds followed by <a href="./profile">
|
echo '<p>Recent posts from feeds followed by <a href="./profile">
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,28 @@
|
||||||
<?php
|
<?php
|
||||||
require_once("partials/base.php");
|
require_once "partials/base.php";
|
||||||
|
|
||||||
$title = "Login - ".$title;
|
$title = "Login - $title";
|
||||||
|
|
||||||
// Password comes from libs/session.php
|
// $password comes from libs/session.php
|
||||||
if (isset($_SESSION['password'])) {
|
if (isset($_SESSION['password'])) {
|
||||||
if ($_SESSION['password'] == $password) {
|
if ($_SESSION['password'] == $passwordInConfig) {
|
||||||
header("Location: .");
|
header("Location: .");
|
||||||
include 'partials/header.php';
|
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
else {
|
|
||||||
include 'partials/header.php';
|
include 'partials/header.php';
|
||||||
?>
|
?>
|
||||||
|
<!-- TODO: Replace center and font tags with CSS -->
|
||||||
<center>
|
<center>
|
||||||
<h2>Enter password or TOTP</h2>
|
<h2>Enter password or TOTP</h2>
|
||||||
<form method="post" action="" id="login_form">
|
<form method="post" action="" id="login_form">
|
||||||
<input type="password" name="pass" placeholder="Password" autofocus><br>
|
<input type="password" name="pass" placeholder="Password" autofocus><br>
|
||||||
<input type="submit" name="submit_pass" value="Login">
|
<input type="submit" name="submit_pass" value="Login">
|
||||||
<p><font style="color:red;"><?php if(isset($error)) {echo $error;}?></font></p>
|
<p><font style="color:red;">
|
||||||
|
<?php if (isset($error)) {
|
||||||
|
echo $error;
|
||||||
|
} ?>
|
||||||
|
</font></p>
|
||||||
</form>
|
</form>
|
||||||
</center>
|
</center>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
require_once "libs/persistent_session.php";
|
||||||
|
|
||||||
session_start();
|
deletePersistentCookie();
|
||||||
session_unset();
|
session_unset();
|
||||||
session_destroy();
|
session_destroy();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
require_once 'libs/session.php';
|
||||||
|
checkValidSessionOrRedirectToLogin();
|
||||||
|
|
||||||
// TODO: Give a warning if the file is not found
|
// TODO: Give a warning if the file is not found
|
||||||
$config = parse_ini_file('private/config.ini');
|
$config = parse_ini_file('private/config.ini');
|
||||||
|
|
||||||
|
|
@ -10,16 +13,10 @@ if ($config['debug_mode']) {
|
||||||
|
|
||||||
$txt_file_path = $config['txt_file_path'];
|
$txt_file_path = $config['txt_file_path'];
|
||||||
$public_txt_url = $config['public_txt_url'];
|
$public_txt_url = $config['public_txt_url'];
|
||||||
|
|
||||||
$timezone = $config['timezone'];
|
$timezone = $config['timezone'];
|
||||||
|
|
||||||
require_once 'libs/session.php';
|
|
||||||
require_once 'libs/load_timezone.php';
|
require_once 'libs/load_timezone.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['password'])) {
|
|
||||||
header('Location: ./login');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_POST['submit'])) {
|
if (isset($_POST['submit'])) {
|
||||||
$new_post = filter_input(INPUT_POST, 'new_post');
|
$new_post = filter_input(INPUT_POST, 'new_post');
|
||||||
$new_post = trim($new_post);
|
$new_post = trim($new_post);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
require_once "partials/base.php";
|
require_once "partials/base.php";
|
||||||
|
require_once 'libs/session.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['password'])) {
|
checkValidSessionOrRedirectToLogin();
|
||||||
header('Location: ./login');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
|
|
||||||
|
|
|
||||||
14
views/test_login.php
Normal file
14
views/test_login.php
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
# A simple text to check if sessions are working OK
|
||||||
|
# Remove it from index.php to hide it from the public
|
||||||
|
require_once "libs/persistent_session.php";
|
||||||
|
|
||||||
|
if (!hasValidSession()) {
|
||||||
|
echo "Not a valid session - Go to /login";
|
||||||
|
#header("Location: /login");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
var_dump($_SESSION);
|
||||||
|
|
||||||
|
echo "Valid session";
|
||||||
|
|
@ -1,20 +1,14 @@
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
require_once "partials/base.php";
|
||||||
|
require_once 'libs/session.php';
|
||||||
|
|
||||||
require_once("partials/base.php");
|
checkValidSessionOrRedirectToLogin();
|
||||||
|
|
||||||
if (!isset($_SESSION['password'])) {
|
$title = "Upload - $title";
|
||||||
header('Location: ./login');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
$title = "Upload - ".$title;
|
|
||||||
|
|
||||||
include_once 'partials/header.php';
|
include_once 'partials/header.php';
|
||||||
|
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
|
|
||||||
// Based on code from: https://www.w3schools.com/php/php_file_upload.asp
|
// Based on code from: https://www.w3schools.com/php/php_file_upload.asp
|
||||||
|
|
||||||
//echo getcwd() ."<br>";
|
//echo getcwd() ."<br>";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue