Commit 541ee899 authored by Hugo Leisink's avatar Hugo Leisink

Release 6.6

parent cf861c8e
banshee (6.6) stable; urgency=low
* Banshee now requires PHP 7.2.
* Password hash algorithm changed to Argon2.
* Dynamic content blocks in static pages.
* DataTables updated to 1.10.19.
* jQuery updated to 3.4.0.
* Bootstrap updated to 3.4.1.
* Small bugfixes and improvements.
-- Hugo Leisink <[email protected]> Tue, 24 Apr 2019 13:41:28 +0200
banshee (6.5) stable; urgency=low
* Preview option and BBcode check in forum module.
......
......@@ -39,6 +39,8 @@
$page["content"] = $this->view->secure_string($page["content"]);
}
/* Page form
*/
if (is_true($page["form"])) {
$page_form = new \Banshee\form_script($this->view, $this->settings, $page["content"]);
if ($_SERVER["REQUEST_METHOD"] == "POST") {
......@@ -56,6 +58,15 @@
}
}
/* Dynamic content block
*/
if (class_exists("Banshee\\dynamic_page_blocks")) {
$dynamic = new Banshee\dynamic_page_blocks($this->db, $this->settings, $this->user, $this->page, $this->view);
$page["content"] = $dynamic->execute($page["content"]);
}
/* Page to view
*/
if (is_true($page["form"])) {
$this->view->add_css("banshee/page_form.css");
......
......@@ -21,7 +21,6 @@
"Dictionary" => array("cms/dictionary", "dictionary.png"),
"F.A.Q." => array("cms/faq", "faq.png"),
"Files" => array("cms/file", "file.png"),
"Forms" => array("cms/form", "form.png"),
"Forum" => array("cms/forum", "forum.png"),
"Guestbook" => array("cms/guestbook", "guestbook.png"),
"Languages" => array("cms/language", "language.png"),
......
......@@ -78,6 +78,13 @@
}
$this->view->close_tag();
/* Dynamic page content
*/
if (class_exists("Banshee\\dynamic_page_blocks")) {
$sections = Banshee\dynamic_page_blocks::available_sections();
$this->view->add_tag("blocks", implode(", ", $sections));
}
/* Page data
*/
$this->view->record($page, "page", $args);
......
......@@ -101,9 +101,6 @@
}
}
if (($_SERVER["REQUEST_METHOD"] == "POST") && ($_POST["submit_button"] == "album")) {
}
if (($album_count = $this->model->count_albums()) === false) {
$this->view->add_tag("result", "Error counting albums");
return;
......
......@@ -27,7 +27,11 @@
$this->view->open_tag("weblogs");
foreach ($weblogs as $weblog) {
$weblog["visible"] = show_boolean($weblog["visible"]);
$weblog["timestamp"] = date("j F Y, H:i", $weblog["timestamp"]);
if ($weblog["timestamp"] !== null) {
$weblog["timestamp"] = date("j F Y, H:i", $weblog["timestamp"]);
} else {
$weblog["timestamp"] = "Not published yet";
}
$this->view->record($weblog, "weblog");
}
$this->view->close_tag();
......
......@@ -11,7 +11,7 @@
$this->view->description = "News";
$this->view->keywords = "news";
$this->view->title = "News";
$this->view->add_alternate("News", "application/rss+xml", "/news.xml");
$this->view->add_alternate($this->settings->head_title." news", "application/rss+xml", "/news.xml");
if ($this->page->type == "xml") {
/* RSS feed
......
......@@ -30,6 +30,7 @@
$this->view->open_tag("weblog", array("id" => $weblog["id"]));
$weblog["timestamp"] = date_string("j F Y, H:i", $weblog["timestamp"]);
$weblog["title_link"] = urlencode($weblog["title"]);
$this->view->record($weblog);
/* Tags
......@@ -61,6 +62,7 @@
$this->view->open_tag("weblog", array("id" => $weblog["id"]));
$this->view->add_tag("title", $weblog["title"]);
$this->view->add_tag("title_link", urlencode($weblog["title"]));
$this->view->add_tag("content", $weblog["content"]);
$this->view->add_tag("author", $weblog["author"]);
$this->view->add_tag("timestamp", $weblog["timestamp"]);
......@@ -108,7 +110,7 @@
$this->view->title = "Weblog";
$this->view->description = "Weblog";
$this->view->keywords = "weblog";
$this->view->add_alternate("Weblog", "application/rss+xml", "/weblog.xml");
$this->view->add_alternate($this->settings->head_title." weblog", "application/rss+xml", "/weblog.xml");
$this->url = array("url" => $this->page->page);
......
This diff is collapsed.
......@@ -77,6 +77,10 @@
}
}
delete_file("libraries/dynamic_page_blocks.php");
delete_file("views/banshee/dynamic_page_blocks.xslt");
delete_file("public/css/banshee/dynamic_page_blocks.css");
/* Demo content on disk
*/
truncate_directory("public/".FILES_PATH);
......
......@@ -37,7 +37,7 @@
print "\n";
} while ($password == "");
$password = hash_password($password, $username);
$password = password_hash($password, PASSWORD_ALGORITHM);
if ($test == false) {
$query = "update users set password=%s where username=%s";
......
......@@ -22,7 +22,7 @@
$font = implode(" ", $argv);
$font = str_replace(" ", "+", $font);
$font_api = new \Banshee\Protocols\HTTPS("fonts.googleapis.com");
$font_api = new Banshee\Protocols\HTTPS("fonts.googleapis.com");
if (($result = $font_api->GET("/css?family=".$font)) === false) {
exit("Fonts API error.\n");
}
......@@ -57,9 +57,9 @@
$path = "/". $path;
if ($protocol == "http:") {
$http = new \Banshee\Protocols\HTTP($hostname);
$http = new Banshee\Protocols\HTTP($hostname);
} else if ($protocol == "https:") {
$http = new \Banshee\Protocols\HTTPS($hostname);
$http = new Banshee\Protocols\HTTPS($hostname);
} else {
printf("Unknow protocol (%s) in font url.\n", $protocol);
exit;
......@@ -67,8 +67,9 @@
$result = $http->GET($path);
$file = "fonts/".str_replace("+", "", $font).".woff";
if (($fp = fopen("fonts/".str_replace("+", "", $font).".woff", "w")) == false) {
$file = str_replace("+", "", $font);
$file = "fonts/".str_replace(":", "-", $file).".woff";
if (($fp = fopen($file, "w")) == false) {
printf("Can't write font file.\n");
exit;
}
......
......@@ -2,17 +2,10 @@
cd `dirname $0`/../public/js
if [ "$1" = "" ]; then
version="4.9.2"
else
version=$1
fi
echo "Downloading latest version of CKEditor 4."
git clone https://github.com/ckeditor/ckeditor-releases.git
echo "Downloading CKEditor v${version}."
wget -qO ckeditor.zip http://download.cksource.com/CKEditor/CKEditor/CKEditor%20${version}/ckeditor_${version}_full.zip
if [ ! -s ckeditor.zip ]; then
rm -f ckeditor.zip
if [ ! -d ckeditor-releases ]; then
echo "Download error."
exit
fi
......@@ -21,14 +14,14 @@ echo "Installing CKEditor."
if [ -d ckeditor ]; then
mv -f ckeditor ckeditor_old
fi
unzip ckeditor.zip > /dev/null
rm -rf ckeditor/samples
rm -rf ckeditor-releases/samples
if [ -d ckeditor_old ]; then
mv -f ckeditor_old/config.js ckeditor
mv -f ckeditor_old/config.js ckeditor-releases
else
cp -f ../../extra/ckeditor_config.js ckeditor/config.js
cp -f ../../extra/ckeditor_config.js ckeditor-releases/config.js
fi
echo "Cleaning up."
rm -rf ckeditor_old
rm -f ckeditor.zip
rm -rf ckeditor
mv ckeditor-releases ckeditor
......@@ -3,32 +3,29 @@
cd `dirname $0`/..
echo "Downloading latest version of TCPDF."
curl -s -o tcpdf.zip https://codeload.github.com/tecnickcom/TCPDF/zip/master
git clone https://github.com/tecnickcom/TCPDF
if [ ! -s tcpdf.zip ]; then
rm -f tcpdf.zip
if [ ! -d TCPDF ]; then
echo "Download error."
exit
fi
echo "Installing TCPDF."
unzip -q tcpdf.zip
mkdir -p libraries/thirdparty/tcpdf
cat TCPDF-master/tcpdf.php | sed "s/require_once(dirname(__FILE__).'.*\//require_once(dirname(__FILE__).'\/tcpdf\//" > libraries/thirdparty/tcpdf.php
cp -f TCPDF-master/tcpdf_barcodes*.php libraries/thirdparty/tcpdf
cp -f TCPDF-master/tcpdf_autoconfig.php libraries/thirdparty/tcpdf
cp -f TCPDF-master/include/*.php libraries/thirdparty/tcpdf
cat TCPDF/tcpdf.php | sed "s/require_once(dirname(__FILE__).'.*\//require_once(dirname(__FILE__).'\/tcpdf\//" > libraries/thirdparty/tcpdf.php
cp -f TCPDF/tcpdf_barcodes*.php libraries/thirdparty/tcpdf
cp -f TCPDF/tcpdf_autoconfig.php libraries/thirdparty/tcpdf
cp -f TCPDF/include/*.php libraries/thirdparty/tcpdf
chmod 644 libraries/thirdparty/tcpdf/*
echo "Installing fonts."
mkdir -p extra/tcpdf_fonts
cp TCPDF-master/fonts/courier*.php extra/tcpdf_fonts
cp TCPDF-master/fonts/helvetica*.php extra/tcpdf_fonts
cp TCPDF-master/fonts/symbol.php extra/tcpdf_fonts
cp TCPDF-master/fonts/times*.php extra/tcpdf_fonts
cp TCPDF-master/fonts/zapfdingbats.php extra/tcpdf_fonts
cp TCPDF/fonts/courier*.php extra/tcpdf_fonts
cp TCPDF/fonts/helvetica*.php extra/tcpdf_fonts
cp TCPDF/fonts/symbol.php extra/tcpdf_fonts
cp TCPDF/fonts/times*.php extra/tcpdf_fonts
cp TCPDF/fonts/zapfdingbats.php extra/tcpdf_fonts
chmod 644 extra/tcpdf_fonts/*
echo "Cleaning up."
rm -f tcpdf.zip
rm -rf TCPDF-master
rm -rf TCPDF
<html>
<body style="background-color:#c0c0c0 ; font-family:sans-serif ; font-size:14px">
<div style="min-height:250px ; max-width:800px ; margin:20px ; padding:15px ; background-color:#ffffff ; border:1px solid #000000 ; border-radius:8px">
<div style="min-height:220px">
<h1 style="margin:10px 0 0 0 ; font-size:20px">[TITLE]</h1>
<div style="line-height:20px"><p>[CONTENT]</p></div>
</div>
<div style="padding-top:15px ; font-size:11px ; border-top:1px solid #e0e0e0">[FOOTER]</div>
<div style="min-height:220px">
<h1 style="margin:10px 0 0 0 ; font-size:20px">[TITLE]</h1>
<div style="line-height:20px"><p>[CONTENT]</p></div>
</div>
<div style="margin-top:15p ; padding-top:15px ; font-size:11px ; border-top:1px solid #e0e0e0">
Banshee website: <a href="https://[SERVER_NAME]/">[SERVER_NAME]</a>
<span style="margin:0 10px">|</span>
To unsubscribe from this newsletter, click <a href="https://[SERVER_NAME]/newsletter">here</a>
</div>
</div>
</body>
</html>
......@@ -12,6 +12,7 @@
private $db = null;
private $page = null;
private $today = null;
private $normal_user = true;
private $required_headers = array("USER_AGENT", "ACCEPT_ENCODING", "ACCEPT_LANGUAGE");
private $search_bots = array("bot", "spider", "crawl", "feed", "rss", "slurp",
"thumbshots", "sogou", "claws", "wotbox", "blogtrottr", "feedbin");
......@@ -34,6 +35,14 @@
$this->page = $page;
}
public function __get($key) {
switch ($key) {
case "normal_user": return $this->normal_user;
}
return null;
}
/* Log visit
*
* INPUT: -
......@@ -125,6 +134,7 @@
foreach ($this->referer_spam as $spam) {
if (strpos($hostname, $spam) !== false) {
$this->normal_user = false;
return;
}
}
......@@ -243,6 +253,7 @@
*/
foreach ($this->search_bots as $bot) {
if (strpos(strtolower($_SERVER["HTTP_USER_AGENT"]), $bot) !== false) {
$this->normal_user = false;
return;
}
}
......@@ -278,6 +289,7 @@
if (strpos($referer, $url) !== false) {
$this->log_search_query($referer);
$search_referer = true;
$this->normal_user = false;
break;
}
}
......
......@@ -6,7 +6,7 @@
* Licensed under The MIT License
*/
define("BANSHEE_VERSION", "6.5");
define("BANSHEE_VERSION", "6.6");
define("ADMIN_ROLE_ID", 1);
define("USER_ROLE_ID", 2);
define("YES", 1);
......@@ -14,7 +14,7 @@
define("USER_STATUS_DISABLED", 0);
define("USER_STATUS_CHANGEPWD", 1);
define("USER_STATUS_ACTIVE", 2);
define("PASSWORD_ITERATIONS", 250000);
define("PASSWORD_ALGORITHM", PASSWORD_ARGON2I);
define("PASSWORD_MIN_LENGTH", 8);
define("PASSWORD_MAX_LENGTH", 1000);
define("ONE_TIME_KEY_SIZE", 32);
......@@ -248,7 +248,7 @@
if (func_num_args() > 1) {
$args = func_get_args();
array_shift($args);
$info = vsprintf($action, $args);
$info = vsprintf($info, $args);
} else if (is_array($info)) {
foreach ($info as $key => $value) {
$info[$key] = "\t".$key." => ".chop($value);
......@@ -407,8 +407,8 @@
/* Check PHP version and settings
*/
if (version_compare(PHP_VERSION, "7") < 0) {
exit("This system uses an unsupported PHP version. Use at least PHP 7.0.");
if (version_compare(PHP_VERSION, "7.2") < 0) {
exit("This system uses an unsupported PHP version. Use at least PHP 7.2.");
}
ini_set("zlib.output_compression", "Off");
?>
......@@ -17,6 +17,7 @@
function exception_handler($error) {
$previous = ob_get_clean();
header("Content-Type: text/html");
print "<!DOCTYPE html><html><body>\n";
print "<h1>Banshee exception</h1>\n";
......
......@@ -178,9 +178,7 @@
$match = true;
for ($i = 0; $i < $parts; $i++) {
if ($page[$i] == "*") {
continue;
} else if ($page[$i] !== $url[$i]) {
if ($page[$i] !== $url[$i]) {
$match = false;
break;
}
......
......@@ -18,16 +18,6 @@
define("VALIDATE_NONEMPTY", 0);
/* Secure password with PBKDF2
*
* INPUT: string password, string salt
* OUTPUT: string hashed password
* ERROR: -
*/
function hash_password($password, $salt) {
return hash_pbkdf2("sha256", $password, hash("sha256", $salt), PASSWORD_ITERATIONS, 0);
}
/* Validate input
*
* INPUT: string input, string valid characters[, int length]
......
......@@ -183,7 +183,7 @@
$this->denied = true;
foreach (array_keys($_COOKIE) as $cookie) {
setcookie($cookie, null, 1);
setcookie($cookie, "", 1);
}
$_SERVER["REQUEST_METHOD"] = "GET";
......@@ -258,7 +258,7 @@
$this->db->query("delete from sessions where id=%d", $this->id);
foreach (array_keys($_COOKIE) as $cookie) {
setcookie($cookie, null, 1);
setcookie($cookie, "", 1);
}
$_SESSION = array();
......
......@@ -131,7 +131,7 @@
}
if (strlen($password) <= PASSWORD_MAX_LENGTH) {
if (hash_equals($user["password"], hash_password($password, $username)) && $auth_code_ok) {
if (password_verify($password, $user["password"]) && $auth_code_ok) {
$this->login((int)$user["id"]);
}
}
......
......@@ -208,17 +208,20 @@
* ERROR: -
*/
public function add_css($css, $prepend = false) {
if (file_exists("css/".$css) == false) {
$css = "/css/".$css;
if (in_array($css, $this->css_links)) {
return true;
}
if (file_exists(".".$css) == false) {
return false;
}
$css = "/css/".$css;
if (in_array($css, $this->css_links) == false) {
if ($prepend) {
array_unshift($this->css_links, $css);
} else {
array_push($this->css_links, $css);
}
if ($prepend) {
array_unshift($this->css_links, $css);
} else {
array_push($this->css_links, $css);
}
return true;
......
<?php
/* Copyright (c) by Hugo Leisink <[email protected]>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace Banshee;
abstract class dynamic_blocks extends model {
private $system_view = null;
private $class = null;
/* Constructor
*
* INPUT: object database, object settings
* OUTPUT: -
* ERROR: -
*/
public function __construct($database, $settings, $user, $page, $view, $language = null) {
$this->system_view = $view;
$xml = new Core\xml($db, is_true(SECURE_XML_DATA));
$arguments = array($database, $settings, $user, $page, $xml, $language);
call_user_func_array(array("parent", "__construct"), $arguments);
$this->class = array_pop(explode("\\", static::class));
}
/* Available sections
*
* INPUT: -
* OUTPUT: array available sections
* ERROR: -
*/
static public function available_sections() {
$methods = get_class_methods(static::class);
$remove = array("__construct", "borrow", "available_sections",
"get_dynamic_content", "execute");
$methods = array_diff($methods, $remove);
sort($methods);
return $methods;
}
/* Execute
*
* INPUT: string content with dynamic tags
* OUTPUT: string content with dynamic content
* ERROR: -
*/
private function get_dynamic_content($section, $parameters) {
if (in_array($section, $this->available_sections()) == false) {
return null;
}
$this->view->clear_buffer();
$this->view->open_tag($section);
if (($result = $this->$section($parameters)) !== null) {
return htmlentities($result);
}
$this->view->close_tag();
return $this->view->transform("../views/banshee/".$this->class.".xslt");
}
/* Execute
*
* INPUT: string content with dynamic tags
* OUTPUT: string content with dynamic content
* ERROR: -
*/
public function execute($content) {
$tags_replaced = 0;
$pos = 0;
while (($pos = strpos($content, "<dynamic ", $pos)) !== false) {
if (($close = strpos($content, "/>", $pos)) === false) {
break;
}
$close += 2;
$tag = substr($content, $pos, $close - $pos);
$parameters = trim(substr($tag, 9, -2));
$parameters = explode(" ", $parameters);
$section = array_shift($parameters);
if (($block = $this->get_dynamic_content($section, $parameters)) !== null) {
$tags_replaced++;
}
$content = substr($content, 0, $pos) . $block . substr($content, $close);
$pos = $close - ($close - $pos) + strlen($block);
}
if ($tags_replaced > 0) {
$this->system_view->add_css("banshee/".$this->class.".css");
}
return $content;
}
}
?>
<?php
namespace Banshee;
class dynamic_page_blocks extends dynamic_blocks {
protected function timestamp() {
$this->view->add_tag("time", date_string("j F Y, H:i:s"));
}
}
?>
......@@ -130,7 +130,8 @@
$item = "<div>Unknown form element defined.</div>\n";
}
$item = "<label for=\"".$elem_id."\">".$element["label"].":".
$separator = in_array(substr($element["label"], -1), array(":", ".", "?")) ? "" : ":";
$item = "<label for=\"".$elem_id."\">".$element["label"].$separator.
($element["required"] ? "<span class=\"required\">*</span>" : "").
"</label>\n".$item;
......@@ -195,6 +196,9 @@
$result = "<table>\n";
foreach ($this->elements as $elem_id => $element) {
if ($element["type"] == "choice") {
list($element["label"], $answers) = explode(":", $element["label"], 2);
}
$result .= sprintf("<tr><td>%s:</td><td>%s</td></tr>\n", $element["label"], $post[$elem_id]);
}
$result .= "</table>\n";
......
......@@ -9,8 +9,6 @@
namespace Banshee;
class newsletter extends Protocols\email {
private $footers = array();
/* Constructor
*
* INPUT: string subject[, string e-mail][, string name]
......@@ -20,21 +18,9 @@
public function __construct($subject, $from_address = null, $from_name = null) {
$subject = utf8_decode($subject);
array_push($this->footers, "Banshee website: <a href=\"http://".$_SERVER["SERVER_NAME"]."/\">".$_SERVER["SERVER_NAME"]."</a>");
array_push($this->footers, "To unsubscribe from this newsletter, click <a href=\"http://".$_SERVER["SERVER_NAME"]."/newsletter\">here</a>.");
parent::__construct($subject, $from_address, $from_name);
}
/* Add e-mail footer
*
* INPUT: string footer
* OUTPUT: -
* ERROR: -
*/
public function add_footer($str) {
array_push($this->footers, $str);
}
/* Set newsletter content
*
* INPUT: string content
......@@ -47,13 +33,11 @@
$content = str_replace("\n\n", "</p>\n<p>", $content);
$content = str_replace("\n", "<br>\n", $content);
$footer = implode("<span style=\"margin:0 10px\">|</span>", $this->footers);
$message = file_get_contents("../extra/newsletter.txt");
$this->set_message_fields(array(
"TITLE" => $this->subject,
"CONTENT" => $content,
"FOOTER" => $footer));
"TITLE" => $this->subject,
"CONTENT" => $content,
"SERVER_NAME" => $_SERVER["SERVER_NAME"]));
parent::message($message);
}
......